This repository was archived by the owner on Oct 2, 2019. It is now read-only.
Refactoring the behavior of "as" combined with "track by"#2028
Open
aurelienlt wants to merge 3 commits intoangular-ui:masterfrom
Open
Refactoring the behavior of "as" combined with "track by"#2028aurelienlt wants to merge 3 commits intoangular-ui:masterfrom
aurelienlt wants to merge 3 commits intoangular-ui:masterfrom
Conversation
added 3 commits
July 5, 2017 17:45
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This pull solves most problem due to the combined usage of "as" and "track by" (#1762, #1756, ...), and most problems of the selected items not being updated by the choices items (#1989, ...). It solves the problem noticed here: https://github.com/angular-ui/ui-select/wiki/ui-select-choices#warning-select-as-and-track-by
This pull is compatible with the old behavior.
For instance, the following expressions are now valid and will result in a perfect matching between the model and the choices items in both single and multiple cases (and are tested):
repeat="person.email as person in people track by person.email"repeat="item.deep.person as item in peopleDeep"repeat="item.deep as item in peopleDeep track by item.deep.person.email"repeat="choice.value.index as choice in list track by choice.value.index"repeat="choice in list track by 2 * choice.index + 1"repeat="choice.value.index as choice in list track by Math.pow(choice.value.index, 2) - Math.ceil(1+choice.value.index/2)"repeat="Math.floor(2+Math.sqrt(choice)) as choice in list track by 6*Math.floor(2+Math.sqrt(choice))-2"Cause of the issues
Currently, the matching between the model and the choices are performed as such:
===... track by itemName.prop, and second compared to the model byangular.equalsThese two behaviors are both pretty approximate (for instance,
item in list track by item.idis not even treated in single mode).Moreover, the model values won't be updated if the refresh function is asynchronous.
Solution
First, the repeat parser has two new properties
$select.parserResult.trackByMapper: a function that turns an item into a "track by" value (null if "track by" is absent or is using$index)$select.parserResult.modelToTrackByMapper: a function that turns a model (as obtained by$select.parserResult.modelMapper(item)) in a "track by" (null if impossible).So
modelToTrackByMapper(modelMapper(item)) === trackByMapper(item)when those two functions exist.Second, a
$select.resolvedproperty (boolean in single mode, array of booleans is multiple mode) is created, saving which selected value has been matched to an item yet.Third, at each formatting, the model (or each model item) is compared to the resolved selected items and the choices items with the following comparisons:
angular.equals(model, item)angular.equals(model, modelMapper(item))trackByMapper(model) === trackByMapper(item)modelToTrackByMapper(model) === trackByMapper(item)Matching between "as" and "track by"
The algorithm is capable of finding the real occurrences of the "as" expression in the "track by" expression as a variable (it excludes the strings, prefixes, suffixes, ...) and will fail when another use of the item is found.
repeat="choice.index as choice in list track by (truc.choice.index || $choice.index || 'choice.index' != 'choice' && 's\'choice.index\'s' != 's\'choice\'s' && choice.index.toUpperCase() + choice.index || 'wrong')"works andmodelToTrackByMapper('right') === "RIGHTright"(fake occurrences ofchoice.indexare not replaced)repeat="choice.name as choice in list track by 2*choice.index+1"does not work, becausechoice.indexis not usingchoice.name(modelToTrackByMapper = null)However, some unlikely corner cases can be problematic: for instance,
repeat="item.a + item.b as item in list track by item.a + item.b * 2"will work and be interpreted as(item.a + item.b) * 2. Butrepeat="(item.a + item.b) as item in list track by (item.a + item.b * 2)"won't work.