Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Orderby not working with dict syntax on ng-repeat

The parameters to orderBy must match property names in an array of objects.

Your data needs to look something like this:

$scope.list2 = [ { id:"2013-01-08T00:00:00", name:'Joe'},
                 { id:"2013-01-09T00:00:00", name:'Sue'}];

Then a filter like this will work:

<div ng-repeat="item in list2 | orderBy:'id':true">

Fiddle.

Note that orderBy works on the entire array (something in your sample code above) and it returns a sorted array. orderBy doesn't know anything about key and value.


this is not implemented. please see here:

https://github.com/angular/angular.js/issues/1286

EDIT (Aug 27, 2013): this issue seems to be resolved now.


I created a custom filter to make this possible for a select list:

.filter('toDictionaryArray', function () {
    return function (obj) {
        if (!(obj instanceof Object)) return obj;

        var arr = [];
        for (var key in obj) {
            arr.push({ key: key, value: obj[key] });
        }
        return arr;
    }
})

the select list ng-options then reads as follows:

<select ng-options="kv.key as kv.value for kv in p.options | toDictionaryArray | orderBy:'value'"></select>

As akonsu says, the feature has been requested here. However, I still couldn't get it to work with the latest (1.3.0) beta.

There's a nice workaround buried in the comments (note this requires underscore, and you'll have to replace references to 'key' with 'value.$key' in the above example):

[Add a filter]:

app.filter('toArray', function() { return function(obj) {
    if (!(obj instanceof Object)) return obj;
    return _.map(obj, function(val, key) {
        return Object.defineProperty(val, '$key', {__proto__: null, value: key});
    });
}});

Example markup:

<div ng-repeat="val in object | toArray | orderBy:'priority' | filter:fieldSearch">
  {{val.$key}} : {{val}} 
</div>

Potential downsides:

  • Object.defineProperty will not work like this in IE8 (if you don't mind making $key enumerable then this is an easy change).
  • If your property values are not objects then you can't set the $key property and this fails.
  • It is not directly integrated into orderBy or ngRepeat so the syntax is different.

Here's a good work around (angular-toArrayFilter):

.filter('toArray', function () {
  return function (obj, addKey) {
    if ( addKey === false ) {
      return Object.keys(obj).map(function(key) {
        return obj[key];
      });
    } else {
      return Object.keys(obj).map(function (key) {
        if(typeof obj[key] == 'object') return Object.defineProperty(obj[key], '$key', {     enumerable: false, value: key});
      });
    }
  };
});