Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to sort object data source in ng-repeat in AngularJS?

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> 

Live example here.

What am I missing?

Please do not suggest solutions with ng-options as I use ui-select2 which is incompatible with ng-options.

like image 249
Misha Moroshko Avatar asked Feb 19 '13 10:02

Misha Moroshko


People also ask

How is sorting implemented in AngularJS?

To sort in descending order, set it as true . You can also use + to sort the data in an ascending and – the data in descending order also . Here with the filters in Angular JS, instead of displaying the various rows, we will be sorting it by ascending and descending order .

How do I get the index of an element in NG-repeat?

Note: The $index variable is used to get the Index of the Row created by ng-repeat directive. Each row of the HTML Table consists of a Button which has been assigned ng-click directive. The $index variable is passed as parameter to the GetRowIndex function.

How do I sort a list in AngularJS?

String: If the array is an array of objects, you can sort the array by the value of one of the object properties. See the examples below. Function: You can create a function to organize the sorting. Array: Use an array if you need more than one object property to determine the sorting order.

What is Ng-repeat in AngularJS?

AngularJS ng-repeat Directive The ng-repeat directive repeats a set of HTML, a given number of times. The set of HTML will be repeated once per item in a collection. The collection must be an array or an object. Note: Each instance of the repetition is given its own scope, which consist of the current item.


1 Answers

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).

like image 154
mhess Avatar answered Nov 07 '22 06:11

mhess