我有一个ng-repeat迭代一组对象,需要一些函数来提取我想要排序的值。
我的ng-repeat看起来像这样:
ng-repeat="row in rows | orderBy: [sortFnOne, sortFnTwo, ...]"
我遇到的问题是,我希望sortFnOne被颠倒过来。这些是使用简单属性提取我无法访问的字符串,因为它正在对数据进行一些转换以生成我尝试排序的这些值。
如果这很简单,我知道我会这样做:
ng-repeat="row in rows | orderBy: ['-id', 'name', '-status', ...]"
如果这些功能只是返回布尔我可以!获取我想要的结果的返回值,但其中一些是返回字符串,有些是以YYYY-MM-DD格式返回日期。
答案 0 :(得分:0)
我自己也遇到过这个限制......无法通过orderBy
过滤器反转函数所做的排序。
据我所知,没有简单的方法可以在原生JavaScript API中重现这种带方向的复合排序(按'A'升序然后按'B'降序排序)。
Array.prototype.sort
通过比较函数提供基本排序(有关详细信息,请参阅MDN docs),但无法在不编写其他比较函数的情况下轻松切换排序顺序(反向),并且它不提供复合排序的解决方案。我们需要的是一个紧凑的表示法来指定多个排序的方向和优先级。
前段时间我写了这个助手来帮助解决这个问题。
var orderByAgeThenName = new OrderByBuilder().asc(getAge).asc(getName).build();
var friendsByAgeThenName = orderByAgeThenName(friends);
var orderByNameThenAge = new OrderByBuilder().desc(getName).asc(getAge).build();
var friendsByNameThenAge = orderByNameThenAge(friends);
这不是角度过滤器,因此只需将其包装在控制器方法中并从模板中调用即可。或者,只需将顺序应用于控制器内的阵列即可。
我想这可以适应角度过滤器......
Runnable Sample:
angular.module('orderByExample', [])
.controller('ExampleController', ['$scope', function($scope) {
var friends =
[{name:'Jon', phone:'555-1212', age:10},
{name:'Zach', phone:'555-2276', age:7},
{name:'Zach', phone:'555-9876', age:19},
{name:'Zach', phone:'555-9276', age:13},
{name:'Mike', phone:'555-4321', age:21},
{name:'Adam', phone:'555-5678', age:35},
{name:'Julie', phone:'555-8765', age:29}];
function getName(f){
return f.name;
}
function getAge(f){
return f.age;
}
var orderByName = new OrderByBuilder().desc(getName).build();
var orderByNameAndAge = new OrderByBuilder().desc(getName).asc(getAge).build();
$scope.friendLists = [
{label:'Not Ordered', friends: friends},
{label:'Name DESC', friends: orderByName(friends)},
{label:'Name DESC, Age ASC', friends: orderByNameAndAge(friends)}
];
}]);
function OrderByBuilder(orderings){
var _orderings = [];
return {
asc: function(fn){
addOrdering(true,fn);
return this;
},
desc: function(fn){
addOrdering(false,fn);
return this;
},
build: build
};
function addOrdering(asc,fn){
_orderings.push({
getterFn: fn,
asc: asc
});
return this;
}
function build(){
var compare = _orderings.reverse().reduce(function(nextComparer, ordering){
return getComparerFn(ordering, nextComparer);
},null);
return function(xs){
return xs.slice().sort(compare);
};
}
// a comparerFn has the following signature:
// function(a: obj, b: obj): int
function getComparerFn(ordering, nextComparer){
var next = nextComparer || function(a,b){ return 0; };
var getVal = ordering.getterFn;
return function(a,b){
var aVal = getVal(a);
var bVal = getVal(b);
if(aVal < bVal){ return ordering.asc ? -1 : 1; }
if(aVal > bVal){ return ordering.asc ? 1 : -1; }
return next(a,b);
};
}
}
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.0-beta.6/angular.min.js"></script>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<div ng-app="orderByExample">
<div ng-controller="ExampleController">
<div class="row">
<div ng-repeat="friendList in friendLists" class="col-sm-4">
<h4>{{friendList.label}}</h4>
<table class="table table-bordered table-condensed">
<tr>
<th>Name</th>
<th>Phone Number</th>
<th>Age</th>
</tr>
<tr ng-repeat="friend in friendList.friends">
<td>{{friend.name}}</td>
<td>{{friend.phone}}</td>
<td>{{friend.age}}</td>
</tr>
</table>
</div>
</div>
</div>
</div>
答案 1 :(得分:0)
Angular允许您提供比较器函数作为orderBy的第三个参数。此比较器功能使您能够指定自己的订购。
这是展示动态复杂排序的Plunk。它从JSON文件加载100条记录,最初按姓氏排序,然后按名字排序。当您按姓氏之外的其他内容排序时,它使用姓氏和名字来打破关系。但是,虽然主要字段上的排序顺序可能会颠倒,但演示的示例仍将按升序对“姓氏”和“名字”进行排序。
$scope.compareData = function(left, right) {
function compareValues(valueLeft, valueRight) {
var valueReturn;
if (!isNaN(parseInt(valueLeft)) && !isNaN(parseInt(valueRight))) {
valueReturn =
((valueLeft * 1) < (valueRight * 1)
? -1
: ((valueLeft * 1) > (valueRight * 1) ? 1 : 0));
} else {
valueReturn = valueLeft.toString().localeCompare(valueRight.toString());
}
return valueReturn;
}
var dataReturn = 0;
if (typeof right === "undefined") {
dataReturn = 1;
} else if (typeof left === "undefined") {
dataReturn = -1;
} else {
var valuesLeft = left.value.split(",");
var valuesRight = right.value.split(",");
for (var i = 0; (i < valuesLeft.length) && (dataReturn === 0); ++i) {
dataReturn = compareValues(valuesLeft[i], valuesRight[i]);
dataReturn *= ($scope.sortReverse && (i > 0)) ? -1 : 1;
}
}
return dataReturn;
}
以上是链接的Plunk中用于比较器的函数。最后请注意,反转字段上的排序就像将结果乘以-1一样简单。