Angular - Can't make ng-repeat orderBy work

倾然丶 夕夏残阳落幕 提交于 2019-11-26 05:27:33

问题


I\'ve tried many examples of ng-repeat with orderBy, but I can\'t make my json work with it.

<div ng-app>
    <script type=\"text/javascript\" src=\"http://code.angularjs.org/1.0.1/angular-1.0.1.js\"></script>
    <div ng:controller=\"Main\">
        <div ng-repeat=\"release in releases| orderBy:\'environment_id\'\">      
            {{release.environment_id}}
        </div>
    </div>
</div>

And the JSON

function Main($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\"
    }
}

It doesn\'t matter what I write, I always get the same order, or I may say, no order at all.


回答1:


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




回答2:


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>



回答3:


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>



回答4:


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);
  }
});



回答5:


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;
    };
});



回答6:


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.




回答7:


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>


来源:https://stackoverflow.com/questions/19387552/angular-cant-make-ng-repeat-orderby-work

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!