Javascript AngularJS 按属性排序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14478106/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
AngularJS sorting by property
提问by PrimosK
What I am trying to do is sort some data by property. Here is example that I tought should work but it doesn't.
我想做的是按属性对一些数据进行排序。这是我认为应该起作用但不起作用的示例。
HTML part:
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 part:
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},
}
}]);
And the result:
结果:
- A -> AData
- B -> BData
- C -> CData
- A -> 数据
- B -> BData
- C -> CData
... that IMHO should look like this:
...恕我直言应该是这样的:
- C -> CData
- B -> BData
- A -> AData
- C -> CData
- B -> BData
- A -> 数据
Did I miss something (here is ready JSFiddleto experiment on)?
我错过了什么(这里准备好了JSFiddle进行实验)?
回答by Armin
AngularJS' orderBy filter does just support arrays - no objects. So you have to write an own small filter, which does the sorting for you.
AngularJS 的 orderBy 过滤器只支持数组——没有对象。所以你必须编写一个自己的小过滤器,为你进行排序。
Or change the format of data you handle with (if you have influence on that). An array containing objects is sortable by native orderBy filter.
或者更改您处理的数据格式(如果您对此有影响)。包含对象的数组可按本机 orderBy 过滤器排序。
Here is my orderObjectByfilter for AngularJS:
这是我的 AngularJS 的orderObjectBy过滤器:
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;
}
});
Usage in your view:
您认为的用法:
<div class="item" ng-repeat="item in items | orderObjectBy:'position'">
//...
</div>
The object needs in this example a position attribute, but you have the flexibility to use any attribute in objects (containing an integer), just by definition in view.
在这个例子中,对象需要一个位置属性,但是你可以灵活地使用对象中的任何属性(包含一个整数),只是根据视图中的定义。
Example JSON:
示例 JSON:
{
"123": {"name": "Test B", "position": "2"},
"456": {"name": "Test A", "position": "1"}
}
Here is a fiddle which shows you the usage: http://jsfiddle.net/4tkj8/1/
这是一个向您展示用法的小提琴:http: //jsfiddle.net/4tkj8/1/
回答by Leon
It's pretty easy, just do it like this
很简单,就这样做
$scope.props = [{order:"1"},{order:"5"},{order:"2"}]
ng-repeat="prop in props | orderBy:'order'"
回答by Eric Steinborn
Don't forget that parseInt() only works for Integer values. To sort string values you need to swap this:
不要忘记 parseInt() 仅适用于整数值。要对字符串值进行排序,您需要交换以下内容:
array.sort(function(a, b){
a = parseInt(a[attribute]);
b = parseInt(b[attribute]);
return a - b;
});
with this:
有了这个:
array.sort(function(a, b){
var alc = a[attribute].toLowerCase(),
blc = b[attribute].toLowerCase();
return alc > blc ? 1 : alc < blc ? -1 : 0;
});
回答by SunnyShah
As you can see in the code of angular-JS ( https://github.com/angular/angular.js/blob/master/src/ng/filter/orderBy.js) ng-repeat does not work with objects. Here is a hack with sortFunction.
正如您在 angular-JS ( https://github.com/angular/angular.js/blob/master/src/ng/filter/orderBy.js)的代码中所见,ng-repeat 不适用于对象。这是 sortFunction 的一个技巧。
http://jsfiddle.net/sunnycpp/qaK56/33/
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;
}
}
}]);
回答by Gal Ben-Haim
according to http://docs.angularjs.org/api/ng.filter:orderBy, orderBy sorts an array. In your case you're passing an object, so You'll have to implement Your own sorting function.
根据http://docs.angularjs.org/api/ng.filter:orderBy, orderBy 对数组进行排序。在您的情况下,您正在传递一个对象,因此您必须实现自己的排序功能。
or pass an array -
或传递一个数组 -
$scope.testData = {
C: {name:"CData", order: 1},
B: {name:"BData", order: 2},
A: {name:"AData", order: 3},
}
take a look at http://jsfiddle.net/qaK56/
回答by Joshua Wooward
You should really improve your JSON structure to fix your problem:
你真的应该改进你的 JSON 结构来解决你的问题:
$scope.testData = [
{name:"CData", order: 1},
{name:"BData", order: 2},
{name:"AData", order: 3},
]
Then you could do
那么你可以做
<li ng-repeat="test in testData | orderBy:order">...</li>
The problem, I think, is that the (key, value) variables are not available to the orderBy filter, and you should not be storing data in your keys anyways
我认为问题在于 orderBy 过滤器无法使用 (key, value) 变量,无论如何您都不应该将数据存储在您的键中
回答by James Harrington
Here is what i did and it works.
I just used a stringified object.
这是我所做的并且它有效。
我只是使用了一个字符串化的对象。
$scope.thread = [
{
mostRecent:{text:'hello world',timeStamp:12345678 }
allMessages:[]
}
{MoreThreads...}
{etc....}
]
<div ng-repeat="message in thread | orderBy : '-mostRecent.timeStamp'" >
<div ng-repeat="message in thread | orderBy : '-mostRecent.timeStamp'" >
if i wanted to sort by text i would do
如果我想按文本排序,我会这样做
orderBy : 'mostRecent.text'
回答by TachikomaGT
I will add my upgraded version of filter which able to supports next syntax:
我将添加能够支持以下语法的升级版过滤器:
ng-repeat="(id, item) in $ctrl.modelData | orderObjectBy:'itemProperty.someOrder':'asc'
app.filter('orderObjectBy', function(){
function byString(o, s) {
s = s.replace(/\[(\w+)\]/g, '.'); // 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;
}
})
Thanks to Armin and Jason for their answers in this thread, and Alnitak in this thread.
感谢 Armin 和 Jason 在这个线程中的回答,以及 Alnitak 在这个线程中的回答。
回答by dipole_moment
Armin's answer + a strict check for object types and non-angular keys such as $resolve
Armin 的回答 + 严格检查对象类型和非角度键,例如 $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;
}
})
回答by dipole_moment
The following allows for the ordering of objects by keyOR by a key within an object.
以下允许按键或按对象内的键对对象进行排序。
In template you can do something like:
在模板中,您可以执行以下操作:
<li ng-repeat="(k,i) in objectList | orderObjectsBy: 'someKey'">
Or even:
甚至:
<li ng-repeat="(k,i) in objectList | orderObjectsBy: 'someObj.someKey'">
The 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;
}
})

