How to sort object data source in ng-repeat in AngularJS?
Solution 1
While you would see this in the thread the author's answer references in a link, I thought it would be good to put up one of the mentioned workarounds up on SO:
It is true that this is technically not implemented, but there is an easy work around if you're willing to change your data model slightly: use a custom filter to generate an array of the object's properties (without replacement). If you add the key field to the objects ("id" in the above case), you should be able to get the behavior your looking for:
app.filter("toArray", function(){
return function(obj) {
var result = [];
angular.forEach(obj, function(val, key) {
result.push(val);
});
return result;
};
});
...
$scope.users = {
1: {name: "John", email: "[email protected]", id: 1},
2: {name: "Elisa", email: "[email protected]", id: 2}
};
Here's the ng-repeat directive that could be used:
<option value="{{user.id}}" ng-repeat="user in users | toArray | orderBy:'name'">{{user.name}}</option>
And here's the plunkr.
Notice that the orderBy
filter takes name
as its parameter and not user.name
.
Unfortunately, adding the id
property to your objects does create potential for mismatch with it's key in the containing object.
In the link you mentioned in your answer, there are also proposed solutions that create the id
property in the user objects on the fly, but I feel like this approach is a little less messy (at the cost of introducing data replication).
Solution 2
OK, I found the answer:
Misha Moroshko
I build products that make humans happier. Previously Front End engineer at Facebook. Now, reimagining live experiences at https://muso.live
Updated on July 23, 2022Comments
-
Misha Moroshko almost 2 years
Suppose I have the following users:
$scope.users = { "2": { email: '[email protected]', name: 'John' }, "3": { email: '[email protected]', name: 'Elisa' } }
I would like to create a
<select>
with the following options:<option value="3">Elisa</option> <option value="2">John</option>
In other words, users should be sorted by name.
I tried the following using the
(key, value) in expression
syntax, but it doesn't work:<option ng-repeat="(user_id, user) in users | orderBy:'user.name'" value="{{ user.id }}"> {{ user.name }} </option>
What am I missing?
Please do not suggest solutions with
ng-options
as I useui-select2
which is incompatible withng-options
. -
mhess over 10 yearsIt might also be worth mentioning that there are no plans to implement it either according to the thread you cite.
-
ak85 over 9 years@BarthZalewski This looks good however how come if I try to reverse the filter nothing changes? can you handle reverse i n cuh as a situation? ng-repeat="user in users | toArray | orderBy:'name' : reverse"
-
Robbie Smith over 8 yearsThis works too when using the (key, value) in users approach too. Well done!
-
Doug about 8 yearsIn response to @ak85's question you would use ng-repeat="user in users | toArray | orderBy:'name' : true" to reverse the list. Boolean true identifies a reverse order.