角度分组滤波器

ebo*_*ard 12 angularjs

在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">
Run Code Online (Sandbox Code Playgroud)

我得到了可怕的"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;
}; 
}).
Run Code Online (Sandbox Code Playgroud)

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

而且,我猜分组逻辑有点天真,但这是另一个故事.任何帮助将不胜感激,因为这让我发疯.

Ben*_*esh 15

这看起来真正的问题是你正在改变你的输入,而不是创建一个新的变量并从你的过滤器输出.这将触发监视任何正在观察您输入的变量的手表.

实际上没有理由在其中添加"分组== 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;
   };
});
Run Code Online (Sandbox Code Playgroud)

HTML

<ul ng-repeat="grouping in items | group:3">
    <li ng-repeat="item in grouping">{{item}}</li>
</ul>
Run Code Online (Sandbox Code Playgroud)

编辑

也许在你的代码中看到所有这些过滤器会更好,但看起来它会导致问题,因为它总是需要在$ 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);
});
Run Code Online (Sandbox Code Playgroud)

然后在你的标记中:

<ul ng-repeat="grouping in blueprintDisplay">
   <li ng-repeat="item in grouping">{{item}}</li>
</ul>
Run Code Online (Sandbox Code Playgroud)

......我确信那里有拼写错误,但那是基本的想法.


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

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

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

给它一个旋转,让我知道它是否适合你.如果没有,我猜其他答案可能会更好.