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

ngRepeat iterates over object in alphabetical order #6210

Closed
cztomsik opened this issue Feb 11, 2014 · 85 comments
Closed

ngRepeat iterates over object in alphabetical order #6210

cztomsik opened this issue Feb 11, 2014 · 85 comments

Comments

@cztomsik
Copy link

This is very unexpected, all major browsers retain order of inserted keys and it is not going to change in any way in future as it would break a lot of existing code.

No matter of that, angular does it its own "way".

Basically it makes this feature completely useless as you can't use it for example for iterating computed averages, and similar great things.

This is major flaw in design and fixing it involves removing one line:

collectionKeys.sort();

Can we at least discuss this? I am highly convinced this (possibly) breaking change should affect minimum people and if orderBy worked on objects too, fixing may be very simple on their side.

@pkozlowski-opensource
Copy link
Member

There was a lot of discussion about it in #1286

@caitp
Copy link
Contributor

caitp commented Feb 11, 2014

@cztomsik, major browsers don't all keep the order of keys added to objects in the same way... So there is actually some issues there.

I agree it would be preferable if the orderBy filter supported object collections as well as arrays, though.

I've set this as PRs plz!, because I believe it should be desirable to fix the orderBy filter to support this use case. If anyone wants to have a go at it, please do =)

In the mean time, you could get around this by simply using arrays instead of objects, IMO.

@caitp caitp added this to the Backlog milestone Feb 11, 2014
khepin pushed a commit to khepin/angular.js that referenced this issue Feb 19, 2014
Allows to use orderBy filter on collection objects and not only arrays.

eg:

	var c = {
		b: {name: 'b'},
		c: {name: 'c'},
		a: {name: 'a'}
	};
	orderBy(c, 'name'); // => [{name: 'a'}, {name: 'b'}, {name: 'c'}];

Closes: angular#6210
khepin pushed a commit to khepin/angular.js that referenced this issue Feb 19, 2014
Allows to use orderBy filter on collection objects and not only arrays.
eg:

	var c = {
		b: {name: 'b'},
		c: {name: 'c'},
		a: {name: 'a'}
	};
	orderBy(c, 'name'); // => [{name: 'a'}, {name: 'b'}, {name: 'c'}];

Closes: angular#6210
khepin pushed a commit to khepin/angular.js that referenced this issue Feb 19, 2014
Allows to use orderBy filter on collection objects and not only arrays.

Closes: angular#6210
@mgurov
Copy link

mgurov commented Feb 28, 2014

+1

5 similar comments
@sricc
Copy link

sricc commented Mar 7, 2014

+1

@kmlx
Copy link

kmlx commented Apr 3, 2014

+1

@kesarion
Copy link

kesarion commented Apr 4, 2014

+1

@pungme
Copy link

pungme commented Apr 15, 2014

+1

@pedrompg
Copy link

+1

@bdecarne
Copy link

+1 !

@CarlosLCervantes
Copy link

+1

5 similar comments
@eugef
Copy link

eugef commented May 27, 2014

+1

@kevingermain
Copy link

+1

@ovcharenkovv
Copy link

+1

@CapMousse
Copy link

+1

@mathielen
Copy link

+1

@petebacondarwin
Copy link
Contributor

It is very easy to fix this with an toArray filter:

Here is a hard-coded solution to an order by on an object issue: http://jsfiddle.net/q48Vt/

Here is a version that uses @finalclass's toArray filter (remembering that this will not work on IE8): http://jsfiddle.net/z8ME5/

Here is a version that uses toArray but actually modifies the original object (and will work on IE8):
http://jsfiddle.net/JHL6X/

I don't expect this to be added to the core but maybe there is enough desire...

@petebacondarwin petebacondarwin modified the milestones: Backlog, Ice Box Aug 3, 2014
@petebacondarwin
Copy link
Contributor

I have been thinking about this some more tonight - instead of going to sleep, which is what I ought to be doing!

First of all, I think @caitp is right that we cannot guarantee to solve what appears to be the main use case, which is to get the DOM elements in the same order in which the properties are defined on the object collection. It appears that most browsers currently do indeed leave this property ordering alone but it is not guaranteed not to change at any point without notice.

That being said I think we can do more here...

A big problem we have at the moment with object collections is that we really want to do the sorting and filtering inside the repeat logic. Filters such as toArray|orderBy are only able to sort object properties before they get to ng-repeat and so can't support certain use cases such as having access to the key when the property values are non-objects.

I have an idea for 1.4. How about we split ng-repeat into two directives:

  • ng-repeat - only works for arrays and iterates over the items in the collection
  • ng-object - only works for object collections but has hooks for providing filtering and sorting functions

This would have a number of benefits.

  • the code for ng-repeat could be much less complicated as it wouldn't have to worry about objects and keys
  • we would be able to do the sorting and filtering at the right place in the code - between watching the object collection and rendering the list of items in the DOM.
  • it would make it clear to developers what the directive does in each case
  • it could well have performance benefits too

Any thoughts on this?

@cztomsik
Copy link
Author

we've been using objects as ordered collections for years so the behaviour is hardly going to change, also any other library iterates objects in enumeration order ($.each, _.each) so why is angular doing it its own way???

@kesarion
Copy link

I don't see why browsers would, all of a sudden, decide to scramble the order of items in an object.

Nobody expects it to be re-ordered alphabetically and I know people are having trouble with this, thinking there's a bug somewhere when they see 2 coming after 10. It's hard to figure it out the first time, because no one expects it, and it's a pain to have to work around it. I would rather risk Chrome (or others) scramble the order than have forced ordering, mostly because I highly doubt such a thing would last more than 1 day before being patched.

I'm all for making alphabetical re-ordering optional and disabled by default. I don't think heavier changes are required at the moment.

@netpoetica
Copy link
Contributor

@kesarion to Angular teams' credit, it is true and a known fact that some browsers / versions of browsers do not respect object property order. The intentions were good I think, in trying to create a consistent behavior across all browsers, but in practice it's a bit overreaching

@caitp
Copy link
Contributor

caitp commented Dec 22, 2014

there are some interoperable features of property enumeration which are never going to change (the usual "don't break the web" stuff, despite not being spec'd), there are other elements of property enumeration which are not interoperable, and which can change --- those non-interoperable elements are why we say that we can't provide any guarantees about ordering --- you think it's guaranteed, but it's really not. It's one of those really stupid things about javascript =)

But the point I'm getting at is really, it doesn't make any difference whether the keys are alphabetically sorted or not --- you shouldn't be enumerating object keys in ngRepeat anyways, because it doesn't really make sense to do it that way (you lose all control, you get varying results in different engines, depending on the keys you use and the things you do with them).

People want the change and they can have it, but honestly it's not really helping you do anything, and it's a really weird thing to depend on.

@petebacondarwin
Copy link
Contributor

We are going to stop automatically sorting properties in ng-repeat in 1.4 - see #10538.

I think that this thread is no longer providing anything valuable to the discussion. Let's focus on the implementation and make sure that we have captured all the possible use cases for iterating over an object collection inside that PR.

@dustinrjo
Copy link

i really don't care either way on this though I'm more with the +1's but just put it in the documentation! I shouldn't have spent 2 hours today trying to sift through why my objects are out of order, finding that it wasn't the json serializer on my server, it wasn't expressjs, it wasn't mongoose, it wasn't the browser, it wasn't angular ui-router but it was the core of angular! I like things that don't break but I like building things fast even more and fixing them when they break if and when my project has the budget for it.

@petebacondarwin
Copy link
Contributor

+1 for documenting this in 1.3.10

@trollboy
Copy link

+1, undocumented "features" that aren't intuitive.

@petebacondarwin
Copy link
Contributor

@trollboy this has been documented at 7fab29f

@trollboy
Copy link

Thanks I see that now. Just the same though, looks like it was out for a while before it was documented (1.3 released in October, this doc change dated 25 days ago) and it isn't very intuitive. It cost me a lot of time as I was doing server side sorts and finally tried a hail mary of returning an array, as it violates FIFO. I'm glad it's being removed for 1.4 due out in march. The only reason I mentioned the lack of documentation and intuitiveness is simply to express the dissatisfaction such causes as to hopefully curtail such in the future. Thanks!

@petebacondarwin
Copy link
Contributor

Actually, I this sorting of keys was the behaviour since before Angular 1.0.0!

@cztomsik
Copy link
Author

A very unexpected behaviour :-)
But it's already fixed in 1.4, so what's this discussion about anyway?

@rakeshjuyal
Copy link

@cztomsik I am using 1.3.11 and it is sorting the keys alphabetically. Let me try 1.4 now 👍

@jainarpit014
Copy link

+1

2 similar comments
@geoidesic
Copy link

+1

@niemyjski
Copy link

+1

@petebacondarwin
Copy link
Contributor

What are the +1s for? This is fixed in master. It would be a breaking change for 1.3 so it will not be fixed there.

@niemyjski
Copy link

Maybe people want to see this in 1.5.. Community decides what goes into 1.5 and it looks like they are speaking with +1s???

@pkozlowski-opensource
Copy link
Member

@niemyjski this is part of 1.4 so I'm not sure what is the story with 1.5 and votes.... In other words: this is already fixed in master and part of 1.4 releases....

@niemyjski
Copy link

odd, I thought I just came across this issue a few hours ago and thus when looking and +1'ed... Maybe it was just an issue with track by that made me think this was happening...

@kris-o3
Copy link

kris-o3 commented Mar 25, 2015

yep, just noticed that an object i created for a dropdown was being rendered, unexpectedly and quite undesirably, in alphabetical rather than in as-is object order.

@aegiz
Copy link

aegiz commented Jun 17, 2015

+1

@pkozlowski-opensource
Copy link
Member

@aegiz: #6210 (comment)

@angular angular locked and limited conversation to collaborators Jun 22, 2015
@Narretz
Copy link
Contributor

Narretz commented Jun 22, 2015

I'm going to lock this issue, because this is fixed. To recap:

Starting with 1.4, the keys are not sorted alphabetically anymore. This is documented as a breaking change here: https://github.com/angular/angular.js/blob/master/CHANGELOG.md#breaking-changes-6 Any behavior that might look like the keys are still sorted alphabetically is possibly a different bug (for which you can open a new issue), or a usage error.

In 1.3.x and before, the keys are still sorted alphabetically, as changing it in these versions would be major breaking change. The docs outline how to work around this problem: https://code.angularjs.org/1.3.16/docs/api/ng/directive/ngRepeat

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