AngularJS按属性sorting

我想要做的是按属性sorting一些数据。 这里是我应该工作的例子,但它没有。

HTML部分:

<div ng-app='myApp'> <div ng-controller="controller"> <ul> <li ng-repeat="(key, value) in testData | orderBy:'value.order'"> {{value.order}}. {{key}} -> {{value.name}} </li> </ul> </div> </div> 

JS部分:

 var myApp = angular.module('myApp', []); myApp.controller('controller', ['$scope', function ($scope) { $scope.testData = { C: {name:"CData", order: 1}, B: {name:"BData", order: 2}, A: {name:"AData", order: 3}, } }]); 

结果是:

  1. A – > AData
  2. B – > BData
  3. C – > CData

…恕我直言,应该是这样的:

  1. C – > CData
  2. B – > BData
  3. A – > AData

我错过了什么(这里准备JSFiddle试验)?

AngularJS的orderByfilter只支持数组 – 没有对象。 所以你必须写一个自己的小filter,它为你sorting。

或者改变你处理的数据格式(如果你有影响的话)。 包含对象的数组可按本机orderByfiltersorting。

这里是我用于AngularJS的orderObjectByfilter:

 app.filter('orderObjectBy', function(){ return function(input, attribute) { if (!angular.isObject(input)) return input; var array = []; for(var objectKey in input) { array.push(input[objectKey]); } array.sort(function(a, b){ a = parseInt(a[attribute]); b = parseInt(b[attribute]); return a - b; }); return array; } }); 

在你看来的用法:

 <div class="item" ng-repeat="item in items | orderObjectBy:'position'"> //... </div> 

在这个例子中,对象需要一个位置属性,但是您可以灵活地使用对象中的任何属性(包含一个整数),只需通过视图中的定义即可。

示例JSON:

 { "123": {"name": "Test B", "position": "2"}, "456": {"name": "Test A", "position": "1"} } 

这是一个小提琴向您显示的用法: http : //jsfiddle.net/4tkj8/1/

这很容易,就这样做

 $scope.props = [{order:"1"},{order:"5"},{order:"2"}] ng-repeat="prop in props | orderBy:'order'" 

不要忘记,parseInt()只适用于整数值。 为了sortingstring值,你需要交换这个:

 array.sort(function(a, b){ a = parseInt(a[attribute]); b = parseInt(b[attribute]); return a - b; }); 

有了这个:

 array.sort(function(a, b){ var alc = a[attribute].toLowerCase(), blc = b[attribute].toLowerCase(); return alc > blc ? 1 : alc < blc ? -1 : 0; }); 

正如你可以在angular-JS的代码中看到的( https://github.com/angular/angular.js/blob/master/src/ng/filter/orderBy.js),ng-repeat不能用于对象。; 这里有一个sortFunction的破解。

http://jsfiddle.net/sunnycpp/qaK56/33/

 <div ng-app='myApp'> <div ng-controller="controller"> <ul> <li ng-repeat="test in testData | orderBy:sortMe()"> Order = {{test.value.order}} -> Key={{test.key}} Name=:{{test.value.name}} </li> </ul> </div> </div> myApp.controller('controller', ['$scope', function ($scope) { var testData = { a:{name:"CData", order: 2}, b:{name:"AData", order: 3}, c:{name:"BData", order: 1} }; $scope.testData = _.map(testData, function(vValue, vKey) { return { key:vKey, value:vValue }; }) ; $scope.sortMe = function() { return function(object) { return object.value.order; } } }]); 

根据http://docs.angularjs.org/api/ng.filter:orderBy,orderBysorting一个数组。; 在你的情况下,你传递一个对象,所以你必须实现自己的sortingfunction。

或传递一个数组 –

 $scope.testData = { C: {name:"CData", order: 1}, B: {name:"BData", order: 2}, A: {name:"AData", order: 3}, } 

看看http://jsfiddle.net/qaK56/

你应该真的改善你的JSON结构来解决你的问题:

 $scope.testData = [ {name:"CData", order: 1}, {name:"BData", order: 2}, {name:"AData", order: 3}, ] 

那你可以做

 <li ng-repeat="test in testData | orderBy:order">...</li> 

我认为,问题在于(key,value)variables对orderByfilter不可用,而且您不应该将数据存储在密钥中

这是我做的,它的工作原理。
我只是使用了一个string化的对象。

 $scope.thread = [ { mostRecent:{text:'hello world',timeStamp:12345678 } allMessages:[] } {MoreThreads...} {etc....} ] 

<div ng-repeat="message in thread | orderBy : '-mostRecent.timeStamp'" >

如果我想通过文本sorting,我会做的

 orderBy : 'mostRecent.text' 

Armin的答案+严格检查对象types和非angular度键(如$resolve

 app.filter('orderObjectBy', function(){ return function(input, attribute) { if (!angular.isObject(input)) return input; var array = []; for(var objectKey in input) { if (typeof(input[objectKey]) === "object" && objectKey.charAt(0) !== "$") array.push(input[objectKey]); } array.sort(function(a, b){ a = parseInt(a[attribute]); b = parseInt(b[attribute]); return a - b; }); return array; } }) 

以下允许通过键或对象内的键来sorting对象

在模板中,您可以执行如下操作:

  <li ng-repeat="(k,i) in objectList | orderObjectsBy: 'someKey'"> 

甚至:

  <li ng-repeat="(k,i) in objectList | orderObjectsBy: 'someObj.someKey'"> 

filter:

 app.filter('orderObjectsBy', function(){ return function(input, attribute) { if (!angular.isObject(input)) return input; // Filter out angular objects. var array = []; for(var objectKey in input) { if (typeof(input[objectKey]) === "object" && objectKey.charAt(0) !== "$") array.push(input[objectKey]); } var attributeChain = attribute.split("."); array.sort(function(a, b){ for (var i=0; i < attributeChain.length; i++) { a = (typeof(a) === "object") && a.hasOwnProperty( attributeChain[i]) ? a[attributeChain[i]] : 0; b = (typeof(b) === "object") && b.hasOwnProperty( attributeChain[i]) ? b[attributeChain[i]] : 0; } return parseInt(a) - parseInt(b); }); return array; } }) 

我将添加我的升级版本的filter,能够支持下一个语法:

 ng-repeat="(id, item) in $ctrl.modelData | orderObjectBy:'itemProperty.someOrder':'asc' 

 app.filter('orderObjectBy', function(){ function byString(o, s) { s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties s = s.replace(/^\./, ''); // strip a leading dot var a = s.split('.'); for (var i = 0, n = a.length; i < n; ++i) { var k = a[i]; if (k in o) { o = o[k]; } else { return; } } return o; } return function(input, attribute, direction) { if (!angular.isObject(input)) return input; var array = []; for(var objectKey in input) { if (input.hasOwnProperty(objectKey)) { array.push(input[objectKey]); } } array.sort(function(a, b){ a = parseInt(byString(a, attribute)); b = parseInt(byString(b, attribute)); return direction == 'asc' ? a - b : b - a; }); return array; } }) 

感谢Armin和Jason在这个主题中的答案,以及在这个主题中的 Alnitak。