angularjs - orderBy自定义比较器

时间:2018-03-12 22:50:49

标签: javascript angularjs

我试图根据可能需要比较多于1个字段的顺序函数显示值列表,因此标准的单参数函数对我来说是不够的。

我希望带有描述的项目位于列表的顶部(无论描述是什么)以及上半部分(带描述)和下半部分(没有描述)我希望按名称按字母顺序排列

我有这样的事情:

<div ng-repeat="item in items | orderBy:memberSort">
  {{item.sortName}} / {{item.description}}
</div>

和比较器:

$scope.memberSort = function(m1, m2) {
    if (m1.description && !m2.description) {
       return -1;
    }
    if (m2.description && !m1.description) {
       return 1;
    }
    return m1.sortName.localCompare(m2.sortName);
};

如何使用这样的比较器而不仅仅是单参数值函数?在上面的代码中,参数m2总是未定义的。

这是一个jsfiddle:https://jsfiddle.net/1Lwg4s2r/15/

虽然这只是当前的一个问题,但一般的问题是如何定义一个接受2个值的比较器函数,而不仅仅是一个将复杂对象映射到值的单参数函数?

2 个答案:

答案 0 :(得分:3)

由于angularjs 1.5.7,Angularjs OrderBy pipe can take a function as comparator,但我认为使用JavaScript array.sort()绑定一个返回排序数组的函数要简单得多。

JSFIDDLE

HTML

<div ng-repeat="item in getSortedItems()">
  {{item.sortName}} / {{item.description}}
</div>

<强> JS

function myCtrl($scope) {
   $scope.items = [
      {description: 'Boss',sortName: 'Joe'},
      //... rest of your items
   ];

   $scope.getSortedItems = function() {
       return $scope.items.sort(function(m1, m2) {
           if (m1.description && !m2.description)
               return -1;

           if (m2.description && !m1.description)
               return 1;

           return m1.sortName.localeCompare(m2.sortName);
       });
   };
}

如果您关心性能,不要使用angularjs过滤器来执行简单的任务,例如排序数组。在我的解决方案中,sort函数执行两次(如果您可以对数组进行排序然后将值分配给绑定变量会更好),在接受的解决方案中执行20次。

答案 1 :(得分:2)

您必须指定memberSort比较器作为orderBy的第三个参数:

angular.module('app', []).controller('myController', function($scope) {
  $scope.items = [    
    { description: '', sortName: 'Bob' },
    { description: '', sortName: 'Steve' },
    { description: '', sortName: 'Mark' },
    { description: 'Member', sortName: 'Kirk' },
    { description: 'Boss', sortName: 'Joe' }
  ];
  $scope.memberSort = function(o1, o2) {
    var m1 = o1.value, m2 = o2.value;
    if (m1.description && !m2.description)
       return -1;    
    if (m2.description && !m1.description)
       return 1;    
    return m1.sortName.localeCompare(m2.sortName);
  };
});
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>

<div ng-app='app' ng-controller="myController">
  <div ng-repeat="item in items | orderBy: 'valueOf()' : false : memberSort">  
    {{item.sortName}} / {{item.description}}
  </div>
</div>