Angular - Can't make ng-repeat orderBy work

a 夏天 提交于 2019-11-26 17:30:55
tymeJV

The orderBy only works with Arrays -- See http://docs.angularjs.org/api/ng.filter:orderBy

Also a great filter to use for Objects instead of Arrays @ Angularjs OrderBy on ng-repeat doesn't work

As mentioned, only arrays are allowed. But to make it simple for you, you could dynamically convert the object into an array via a piping function as seen here https://gist.github.com/brev/3949705

Just declare the filter, and add it to ng-repeat :)

<div ng-app="myApp">
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script>
<div ng-controller="Main">
  <div ng-repeat="release in releases | object2Array | orderBy:'environment_id'">{{release.environment_id}}</div>
</div>

<script>

var app = angular.module('myApp', []).filter('object2Array', function() {
    return function(input) {
      var out = []; 
      for(i in input){
        out.push(input[i]);
      }
      return out;
    }
  })
.controller('Main',function ($scope) {
        $scope.releases = {"tvl-c-wbap001 + tvl-webapp":{"timestamp":" 05:05:53 PM ","environment_id":"CERT5","release_header":"Projects/Dev","date":"19 Oct","release":"12.11.91-1"},"tvl-c-wbap401 + tvl-webapp":{"timestamp":" 10:07:25 AM ","environment_id":"CERT4","release_header":"Future Release","date":"15 Oct","release":"485-1"},"tvl-c-wbap301 + tvl-webapp":{"timestamp":" 07:59:48 AM ","environment_id":"CERT3","release_header":"Next Release","date":"15 Oct","release":"485-1"},"tvl-c-wbap201 + tvl-webapp":{"timestamp":" 03:34:07 AM ","environment_id":"CERT2","release_header":"Next Changes","date":"15 Oct","release":"13.12.3-1"},"tvl-c-wbap101 + tvl-webapp":{"timestamp":" 12:44:23 AM ","environment_id":"CERT1","release_header":"Production Mirror","date":"15 Oct","release":"13.11.309-1"},"tvl-s-wbap002 + tvl-webapp":{"timestamp":" 12:43:23 AM ","environment_id":"Stage2","date":"15 Oct","release":"13.11.310-1"},"tvl-s-wbap001 + tvl-webapp":{"timestamp":" 11:07:38 AM ","environment_id":"Stage1","release_header":"Production Mirror","date":"11 Oct","release":"13.11.310-1"},"tvl-p-wbap001 + tvl-webapp":{"timestamp":" 11:39:25 PM ","environment_id":"Production","release_header":"Pilots","date":"14 Oct","release":"13.11.310-1"},"tvl-p-wbap100 + tvl-webapp":{"timestamp":" 03:27:53 AM ","environment_id":"Production","release_header":"Non Pilots","date":"11 Oct","release":"13.11.309-1"}}
    });
</script>

the built-in orderBy filter will no longer work when iterating an object. It’s ignored due to the way that object fields are stored. You need create a custom filter

yourApp.filter('orderObjectBy', function() {
  return function(items, field, reverse) {
    var filtered = [];
    angular.forEach(items, function(item) {
      filtered.push(item);
    });
    filtered.sort(function (a, b) {
      return (a[field] > b[field] ? 1 : -1);
    });
    if(reverse) filtered.reverse();
    return filtered;
  };
});

<ul>
<li ng-repeat="item in items | orderObjectBy:'color':true">{{ item.color }}</li>
</ul>

in Eike Thies's response above, if we use underscore.js, filter could be simplified to :

var app = angular.module('myApp', []).filter('object2Array', function() {
  return function(input) {
    return _.toArray(input);
  }
});

Here's a version of @Julian Mosquera's code that also supports sorting by object key:

yourApp.filter('orderObjectBy', function () {
    return function (items, field, reverse) {
        // Build array
        var filtered = [];
        for (var key in items) {
            if (field === 'key')
                filtered.push(key);
            else
                filtered.push(items[key]);
        }
        // Sort array
        filtered.sort(function (a, b) {
            if (field === 'key')
                return (a > b ? 1 : -1);
            else
                return (a[field] > b[field] ? 1 : -1);
        });
        // Reverse array
        if (reverse)
            filtered.reverse();
        return filtered;
    };
});

You're going to have to reformat your releases object to be an array of objects. Then you'll be able to sort them the way you're attempting.

orderby works on arrays that contain objects with immidiate values which can be used as filters, ie

controller.images = [{favs:1,name:"something"},{favs:0,name:"something else"}];

When the above array is repeated, you may use | orderBy:'favs' to refer to that value immidiately, or use a minus in front to order descending

<div class="timeline-image" ng-repeat="image in controller.images | orderBy:'-favs'">
    <img ng-src="{{ images.name }}"/>
</div>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!