Ng- 重复中的自定义排序函数

我有一组瓦片,它们根据用户选择的选项显示某个数字。现在我想实现一个排序,不管显示的是什么数字。

下面的代码显示了我是如何实现它的(通过在父贺卡作用域中获取/设置一个值)。现在,因为 orderBy 函数接受一个字符串,所以我尝试在 card 作用域中设置一个名为 curOptionValue 的变量,并根据该变量进行排序,但它似乎不起作用。

所以问题变成了,如何创建自定义排序函数?

<div ng-controller="aggViewport" >
<div class="btn-group" >
<button ng-click="setOption(opt.name)" ng-repeat="opt in optList" class="btn active">{{opt.name}}</button>
</div>
<div id="container" iso-grid width="500px" height="500px">
<div ng-repeat="card in cards" class="item {{card.class}}" ng-controller="aggCardController">
<table width="100%">
<tr>
<td align="center">
<h4>{{card.name}}</h4>
</td>
</tr>
<tr>
<td align="center"><h2>{{getOption()}}</h2></td>
</tr>
</table>
</div>
</div>

控制器:

module.controller('aggViewport',['$scope','$location',function($scope,$location) {
$scope.cards = [
{name: card1, values: {opt1: 9, opt2: 10}},
{name: card1, values: {opt1: 9, opt2: 10}}
];


$scope.option = "opt1";


$scope.setOption = function(val){
$scope.option = val;
}


}]);


module.controller('aggCardController',['$scope',function($scope){
$scope.getOption = function(){
return $scope.card.values[$scope.option];
}
}]);
152339 次浏览

实际上,orderBy过滤器不仅可以作为字符串的参数,还可以作为函数的参数。摘自 orderBy文档: https://docs.angularjs.org/api/ng/filter/orderBy) :

函数: Getter 函数。这个函数的结果将被排序 使用 < ,= ,> 运算符。

所以,你可以写自己的函数。例如,如果你想根据 opt1和 opt2的和来比较卡片(这是我编的,关键是你可以有任意的函数) ,你可以在你的控制器中写:

$scope.myValueFunction = function(card) {
return card.values.opt1 + card.values.opt2;
};

然后,在你的模板中:

ng-repeat="card in cards | orderBy:myValueFunction"

这是正在工作的 jsFiddle

另一件值得注意的事情是,orderBy只是 AngularJS filters的一个例子,所以如果您需要一个非常具体的排序行为,您可以编写自己的过滤器(尽管 orderBy应该足以满足大多数用例)。

可接受的解决方案只适用于数组,而不适用于对象或关联数组。遗憾的是,由于 Angular 依赖于数组枚举的 JavaScript 实现,因此无法始终如一地控制对象属性的顺序。有些浏览器可能按照字典顺序迭代对象属性,但这是不能保证的。

例如:

$scope.cards = {
"card2": {
values: {
opt1: 9,
opt2: 12
}
},
"card1": {
values: {
opt1: 9,
opt2: 11
}
}
};

指令 <ul ng-repeat="(key, card) in cards | orderBy:myValueFunction">,ng-repeat 可以在“ card 2”之前迭代“ card 1”,而不管排序顺序如何。

To workaround this, we can create a custom filter to convert the object to an array, and then apply a custom sort function before returning the collection.

myApp.filter('orderByValue', function () {
// custom value function for sorting
function myValueFunction(card) {
return card.values.opt1 + card.values.opt2;
}


return function (obj) {
var array = [];
Object.keys(obj).forEach(function (key) {
// inject key into each object so we can refer to it from the template
obj[key].name = key;
array.push(obj[key]);
});
// apply a custom sorting function
array.sort(function (a, b) {
return myValueFunction(b) - myValueFunction(a);
});
return array;
};
});

We cannot iterate over (key, value) pairings in conjunction with custom filters (since the keys for arrays are numerical indexes), so the template should be updated to reference the injected key names.

<ul ng-repeat="card in cards | orderByValue">
<li>\{\{card.name}} \{\{value(card)}}</li>
</ul>

下面是一个工作小提琴使用一个自定义过滤器的关联数组: http://jsfiddle.net/av1mLpqx/1/

Reference: https://github.com/angular/angular.js/issues/1286#issuecomment-22193332

下面的链接非常好地解释了角度滤波器。它展示了如何在 ng- 重复内定义自定义排序逻辑。 Http://toddmotto.com/everything-about-custom-filters-in-angular-js

对于使用属性对对象进行排序,下面是我使用的代码: (注意,这种排序是标准的 JavaScript 排序方法,不是特定于角度的) Column Name 是要执行排序的属性的名称。

self.myArray.sort(function(itemA, itemB) {
if (self.sortOrder === "ASC") {
return itemA[columnName] > itemB[columnName];
} else {
return itemA[columnName] < itemB[columnName];
}
});

在 orderBy 函数中包含方向:

ng-repeat="card in cards | orderBy:myOrderbyFunction():defaultSortDirection"

哪里

defaultSortDirection = 0; // 0 = Ascending, 1 = Descending