orderBy在内部循环中嵌套的ng-repeat

时间:2014-12-17 04:35:36

标签: javascript angularjs nested-loops

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

<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&amp; cat2。如果排名为6,2,5的网站是cat2中的cat1和9,1那么结果将是2,5,6,1,9。我希望结果是1,2,5,6,9。如何我应该这样做吗?

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

1 个答案:

答案 0 :(得分:2)

我认为你想做什么,不能按原样做。无论如何,你可以使用custom filter

新答案

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

&#13;
&#13;
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;
     });
  };
}]);
&#13;
<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>
&#13;
&#13;
&#13;

Old Ansewer

Se代码评论。

&#13;
&#13;
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;
      });
  };
}]);
&#13;
<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>
&#13;
&#13;
&#13;