ng-repeat中的自定义排序功能


113

我有一组显示一定数量的磁贴,具体取决于用户选择的选项。我现在想通过显示的任何数字来实现排序。

下面的代码显示了我是如何实现的(通过在父卡范围内获取/设置一个值)。现在,由于orderBy函数需要一个字符串,因此我尝试在卡范围内设置一个名为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];
    }
}]);

Answers:


192

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

函数:吸气功能。该函数的结果将使用<,=,>运算符进行排序。

因此,您可以编写自己的函数。例如,如果您想基于opt1和opt2之和来比较卡(我正在弥补这一点,关键是您可以具有任意函数),则可以在控制器中编写:

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

然后,在您的模板中:

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

这是工作的jsFiddle

另一点值得注意的是,这orderBy只是AngularJS过滤器的一个示例,因此,如果您需要非常特定的排序行为,则可以编写自己的过滤器(尽管orderBy对于大多数用例来说已经足够了)。


很好,但是也可以为此创建过滤器吗?
雨果·德·洪里格2013年

是的,它仍在工作。这是更新版本
jahller

为什么在文档中没有关于多个参数的描述?顺便说一句:谢谢,它有效。:)
mayankcpdixit

您知道我可以用这种方法处理多个条件吗?如何从myValueFunction返回多个值?
akcasoy 2015年

26

公认的解决方案仅适用于数组,而不适用于对象或关联数组。不幸的是,由于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可以在“ card2”之前迭代“ card1”,而与排序顺序无关。

要解决此问题,我们可以创建一个自定义过滤器以将对象转换为数组,然后在返回集合之前应用自定义排序功能。

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;
  };
});

我们不能与自定义过滤器一起迭代(键,值)对(因为数组的键是数字索引),因此应更新模板以引用注入的键名。

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

这是在关联数组上使用自定义过滤器的有效提琴:http : //jsfiddle.net/av1mLpqx/1/

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


1
我知道我不应该,但我必须-谢谢。
Elia Weiss

7

以下链接很好地说明了Angular中的过滤器。它显示了如何在ng-repeat中定义自定义排序逻辑。 http://toddmotto.com/everything-about-custom-filters-in-angular-js

为了对具有属性的对象进行排序,这是我使用的代码:(请注意,此排序是标准的JavaScript排序方法,而不是特定于angular的)。Column Name是要对其进行排序的属性的名称。

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

0

要将方向与orderBy函数一起包括:

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

哪里

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

emmmmm,只是想了一下,我观察到您写的 myOrderbyFunction()不是,而是写的myOrderbyFunction没有(),它被每两对元素调用以提供自定义排序。
维克多
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.