Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

fix(ngOptions): iterate over the options collection in the same way as `... #11771

Closed
wants to merge 0 commits into from

Conversation

petebacondarwin
Copy link
Contributor

...ngRepeat`

In ngRepeat if the object to be iterated over is "array-like" then it only iterates
over the numerical indexes rather than every key on the object. This prevents "helper"
methods from being included in the rendered collection.

This commit changes ngOptions to iterate in the same way.

BREAKING CHANGE:

Although it is unlikely that anyone is using it in this way, this change does change the
behaviour of ngOptions in the following case:

  • you are iterating over an array-like object, using the array form of the ngOptions syntax
    (item.label for item in items) and that object contains non-numeric property keys.

In this case these properties with non-numeric keys will be ignored.

** Here array-like is defined by the result of a call to this internal function:
https://github.com/angular/angular.js/blob/v1.4.0-rc.1/src/Angular.js#L198-L211 **

To get the desired behaviour you need to iterate using the object form of the ngOptions syntax
(value.label for (key, value) in items)`).

Closes #11733


// Ignore "angular" properties that start with $ or $$
if (key.charAt(0) === '$') return;
if (key.charAt && key.charAt(0) === '$') return;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually this line is no longer needed as it is dealt with in the key extraction logic above

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And it is actually totally wrong now that it is not using forEach

@petebacondarwin
Copy link
Contributor Author

I refactored the code to make it cleaner, rather than follow the ngRepeat logic and ran the ng-options-bp benchmark on both strategies. You can see the refactored code here 864bee5

Code Strategy add-options set-model-1 set-model-2 remove-options set-view-1 set-view-2
ngRepeat style 7.45 7.39 13.90 0.03 14.32 12.72
Clean style 13.83 10.77 24.80 0.02 21.32 23.02

It seems clear that it is best to leave the logic as it is. @caitp if you want to look into why the refactored version was so much slower that would be great and we can do a refact commit later.

But in the meantime I am going to go with the ngRepeat style.

@caitp
Copy link
Contributor

caitp commented May 1, 2015

using forEach will include the HasProperty check, which is super slow. We don't care about holes in arrays, so we don't want to eat that performance hit.

@petebacondarwin
Copy link
Contributor Author

Right, I was using forEach because if the collection is only "array-like" then it wouldn't necessarily have the Array.prototype.forEach method available.

@caitp
Copy link
Contributor

caitp commented May 1, 2015

Well, ignoring "holes" in arrays has been asked for, and forEach() would do it, but then you get the performance issue that we don't like --- a way around that is to just write a quick fast version of forEach that only deals with array-like types, and always ignores holes

@petebacondarwin
Copy link
Contributor Author

I am going to land this and leave refactoring for post 1.4.0

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ng-options include array properties
3 participants