12

ng-repeat 中的 angular.js 条件标记之后,我尝试编写一个自定义过滤器来进行分组。我遇到了关于对象身份和被监视更改的模型的问题,但我认为我终于解决了,因为控制台中不再出现错误。

原来我错了,因为现在当我尝试将它与其他过滤器(用于分页)结合起来时

<div ng-repeat="r in blueprints | orderBy:sortPty | startFrom:currentPage*pageSize | limitTo:pageSize | group:3">
      <div ng-repeat="b in r">

我得到了可怕的“达到了 10 个 $digest() 迭代。中止!” 再次出现错误信息。

这是我的组过滤器:

filter('group', function() {
  return function(input, size) {
    if (input.grouped === true) {
      return input;
    }
  var result=[];
  var temp = [];
  for (var i = 0 ; i < input.length ; i++) {
      temp.push(input[i]);
      if (i % size === 2) {
          result.push(temp);
          temp = [];
      }
  }
  if (temp.length > 0) {
      result.push(temp);
  }
  angular.copy(result, input);
  input.grouped = true;
  return input;
}; 
}).

请注意输入中的使用angular.copy.grouped标记,但无济于事:(我知道例如 “10 $digest() 迭代已达到。中止!”由于使用 angularjs 进行过滤,但显然我没有得到它。

此外,我猜分组逻辑有点幼稚,但那是另一回事了。任何帮助将不胜感激,因为这让我发疯。

4

3 回答 3

15

看起来真正的问题是您正在更改输入,而不是创建新变量并从过滤器中输出。这将触发任何正在监视您输入的变量的监视。

确实没有理由在其中添加“grouped == true”检查,因为您应该完全控制自己的过滤器。但是,如果这对您的应用程序来说是必须的,那么您需要将“grouped == true”添加到过滤器的结果中,而不是输入中。

过滤器的工作方式是它们改变输入并返回不同的东西,然后下一个过滤器处理以前的过滤器结果......所以你的“过滤”检查item in items | filter1 | filter2 | filter3在 filter1 过滤项目,filter2 过滤 filter1 的结果和filter3 过滤过滤器 2 的结果...如果有意义的话。

这是我刚刚整理的东西。我不确定(还)它是否有效,但它给了你基本的想法。您将在一侧取出一个数组,然后在另一侧吐出一组数组。

app.filter('group', function(){
   return function(items, groupSize) {
      var groups = [],
         inner;
      for(var i = 0; i < items.length; i++) {
         if(i % groupSize === 0) {
            inner = [];
            groups.push(inner);
         }
         inner.push(items[i]);
      }
      return groups;
   };
});

HTML

<ul ng-repeat="grouping in items | group:3">
    <li ng-repeat="item in grouping">{{item}}</li>
</ul>

编辑

也许在代码中看到所有这些过滤器会更好,但它看起来会导致问题,因为它经常需要在 $digest 上重新评估。所以我建议你做这样的事情:

app.controller('MyCtrl', function($scope, $filter) {
   $scope.blueprints = [ /* your data */ ];
   $scope.currentPage = 0;
   $scope.pageSize = 30;
   $scope.groupSize = 3;
   $scope.sortPty = 'stuff';

   //load our filters
   var orderBy = $filter('orderBy'),
       startFrom = $filter('startFrom'),
       limitTo = $filter('limitTo'),
       group = $filter('group'); //from the filter above

   //a method to apply the filters.
   function updateBlueprintDisplay(blueprints) {
        var result = orderBy(blueprints, $scope.sortPty);
        result = startForm(result, $scope.currentPage * $scope.pageSize);
        result = limitTo(result, $scope.pageSize);
        result = group(result, 3);
        $scope.blueprintDisplay = result;
   }

   //apply them to the initial value.
   updateBlueprintDisplay();

   //watch for changes.
   $scope.$watch('blueprints', updateBlueprintDisplay);
});

然后在您的标记中:

<ul ng-repeat="grouping in blueprintDisplay">
   <li ng-repeat="item in grouping">{{item}}</li>
</ul>

...我确定那里有错别字,但这是基本思想。


再次编辑:我知道您已经接受了这个答案,但是我最近了解到还有另一种方法,您可能会更喜欢:

<div ng-repeat="item in groupedItems = (items | group:3 | filter1 | filter2)">
    <div ng-repeat="subitem in items.subitems">
    {{subitem}}
    </div>
</div>

这将在您的 $scope 上创建一个名为 $scope.groupedItems 的新属性,它应该有效地缓存您过滤和分组的结果。

试一试,让我知道它是否适合你。如果没有,我想其他答案可能会更好。

于 2013-01-22T16:22:10.853 回答
3

无论如何,我仍然看到 $digest 错误,这令人费解:plnkr.co/edit/tHm8uYfjn8EJk3cG31DP – blesh 1 月 22 日 17:21

这是使用下划线的 memoize 功能修复 $digest 错误的plunker :http: //underscorejs.org/#memoize

问题是 Angular 在每次迭代期间尝试将过滤后的集合作为不同的集合处理。要确保过滤器的返回始终返回相同的对象,请使用 memoize。

http://en.wikipedia.org/wiki/Memoization

下划线分组的另一个示例:Angular 过滤器有效,但导致“达到 10 个 $digest 迭代”

于 2013-10-19T20:24:02.280 回答
1

您可以使用 angular.filter 模块的 groupBy 过滤器并执行以下操作:
用法:(key, value) in collection | groupBy: 'property''propperty.nested'
JS:

$scope.players = [
  {name: 'Gene', team: 'alpha'},
  {name: 'George', team: 'beta'},
  {name: 'Steve', team: 'gamma'},
  {name: 'Paula', team: 'beta'},
  {name: 'Scruath', team: 'gamma'}
];

HTML:

<ul ng-repeat="(key, value) in players | groupBy: 'team'" >
  Group name: {{ key }}
  <li ng-repeat="player in value">
    player: {{ player.name }} 
  </li>
</ul>
<!-- result:
  Group name: alpha
    * player: Gene
  Group name: beta
    * player: George
    * player: Paula
  Group name: gamma
    * player: Steve
    * player: Scruath
于 2014-07-30T10:22:22.367 回答