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}, } }]);
结果是:
- A – > AData
- B – > BData
- C – > CData
…恕我直言,应该是这样的:
- C – > CData
- B – > BData
- 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}, }
你应该真的改善你的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。