在嵌套的 ng 重复的内部循环中排序

orderBy in inner loop on nested ng-repeat

本文关键字:循环 内部 排序 嵌套 ng      更新时间:2023-09-26

我想过滤过滤类别中的网站,并按排名顺序显示它们。代码片段为:

<div ng-repeat="category in categories | filter:{will return more than one category}">
    <div ng-repeat="website in websites | orderBy:'rank'| filter:{ parent_id : category.id }:true">
      {{website.title}},{{website.rank}}
   </div>
</div>

但是在嵌套循环中,由于 orderby 在内部循环中,它适用于外部循环的每次迭代,但总体结果没有根据等级排序。假设有三个类别,过滤器给出 cat1 和 cat2。如果排名为 6,2,5 的网站是 cat1,在 cat2 中是 9,1,那么结果将是 2,5,6,1,9.我希望结果是 1,2,5,6,9.我该怎么办?

我应该在某个函数中传递类别并编写 js 代码来获取过滤网站的数组,然后对它们进行排序并将它们返回到模板,或者是否有其他更好的方法可以在模板本身中做到这一点?

我认为你想做的事情,不能按原样完成。无论如何,您可以使用自定义过滤器。

新答案

此方法为您提供了类别选择机制,作为如何使用此自定义筛选器的另一个示例。

angular.module('app',[])
// categories
.value('categories',  [ { id: 0, title:"first" }, { id: 1, title:"second" }, { id: 2, title:"third" } ])
// websites
.value('websites',  [   { rank: 3, parent_id: 2, title: "Alice" },
                        { rank: 1, parent_id: 1, title: "Bob" },
                        { rank: 9, parent_id: 1, title: "Carol" },
                        { rank: 2, parent_id: 0, title: "David" },
                        { rank: 4, parent_id: 0, title: "Emma" },
                        { rank: 5, parent_id: 0, title: "Foo" } ])
// controller, 
.controller('ctrl', ['$scope', 'categories', 'websites', function($scope, categories, websites) {
    // categories injected
    $scope.categories = categories;
    // websites injected
    $scope.websites = websites;  
    // categories selection helper, useful for preselection
    $scope.selection = { 0: true, 1:false }  // 2: false (implicit)
  
}])
                     
// categories filter, categories injected.
.filter('bycat', ['categories', function(categories) {
  // websites is the result of orderBy :'rank', selection helper passed as paramenter.
  return function(websites, selection) {
    
    // just an Array.prototype.filter
    return websites.filter(function(website) {
          // for each category                    
          for(var i=0; i < categories.length; i++) {
              var cat = categories[i];
              // if category is selected and website belongs to category
              if (selection[cat.id] && cat.id == website.parent_id) { 
                  // include this website
                  return true;
              } 
          }
          // exclude this website
          return false;
     });
  };
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
  <span ng-repeat="category in categories">
      <label class="checkbox" for="{{category.id}}">
        <input type="checkbox" ng-model="selection[category.id]" name="group" id="{{category.id}}" />
        {{category.title}}
      </label>
    </span>
  <div ng-repeat="website in websites | orderBy:'rank'| bycat: selection">
    <p>Rank:{{website.rank}} - {{website.title}} ({{categories[website.parent_id].title}})</p>
  </div>
</div>

老安下水道

Se 代码注释。

angular.module('app',[])
// categories will be injected in custom filter.
.value('categories',  [ { id: 1, title:"first" }, { id: 2, title:"second" } ])
.controller('ctrl', function($scope) {        
    // sample websites
    $scope.websites = [ { rank: 1, parent_id: 2, title: "Site w/rank 1" },
                        { rank: 9, parent_id: 2, title: "Site w/rank 9" },
                        { rank: 2, parent_id: 1, title: "Site w/rank 2" },
                        { rank: 4, parent_id: 1, title: "Site w/rank 4" },
                        { rank: 5, parent_id: 1, title: "Site w/rank 5" } ];
  
})
// custom filter, categories injected.
.filter('bycat', ['categories', function(categories) {
  // websites is the result of orderBy :'rank'
  return function(websites, catText) {    
    
    // just an Array.prototype.filter
    return websites.filter(function(website) {
          // if no filter, show all.
          if (!catText) return true;
         
          for(var i=0; i < categories.length; i++) {
              var cat = categories[i];
              // if matches cat.title and id == parent_id, gotcha!
              if (cat.title.indexOf(catText) != -1 && cat.id == website.parent_id) { 
                  return true;
              } 
          }
          // else were 
          return false;
      });
  };
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
  <input type="text" ng-model="filterText">
  <p>Try "first" and "second"</p>
  <div ng-repeat="website in websites | orderBy:'rank'| bycat: filterText ">
    {{website.title}},{{website.rank}}
  </div>
</div>