【问题标题】:Is it possible to filter angular.js by containment in another array?是否可以通过包含在另一个数组中来过滤 angular.js?
【发布时间】:2013-03-05 11:53:18
【问题描述】:

所以如果我有一个数组:

$scope.letters = 
[{"id":"a"},
{"id":"b"},
{"id":"c"}];

还有一个数组

$scope.filterBy = ["b","c","d"];

我想要一些 ng-repeat 来过滤 $scope.letters 仅通过出现在 $filterBy 中的项目。

我希望能够做一些事情:

<span ng-repeat="{{letter in letters|filter: letter.id in filterBy }} > {{letter.id}} </span>

并让它打印 b,c

我知道这是一个非常愚蠢的例子,但是有没有办法根据另一个数组对象的内容过滤 angular.js 表达式?

【问题讨论】:

    标签: arrays angularjs filtering


    【解决方案1】:

    你应该尝试这样的事情:

    JS:

    angular.module('Test', []);
    
    function Ctrl($scope) {
      $scope.letters = [
        {id: 'a'},
        {id: 'b'},
        {id: 'c'}
      ];
    
      $scope.filterBy = ['b', 'c', 'd'];
    
      $scope.filteredLetters = function () {
        return $scope.letters.filter(function (letter) {
          return $scope.filterBy.indexOf(letter.id) !== -1;
        });
      };
    }
    
    Ctrl.$inject = ['$scope'];
    

    HTML:

    <div ng-repeat='letter in filteredLetters(letters)'>{{letter.id}}</div>
    

    你可以试试live example

    【讨论】:

    • filteredLetters() 将被调用每个摘要周期。因此,如果您在视图中使用 ng-model 在输入字段中,这意味着每次击键。最好将过滤器的结果存储在新的 $scope 属性上。如果lettersfilterBy 发生变化,使用$watch()es 更新过滤结果。
    • 虽然它可以工作(前提是您的应用程序非常简单)我不建议使用这种方法 - 正如@MarkRajcok 提到的那样,它被称为每个摘要周期,这意味着性能很糟糕,我从角度得到错误类似于“错误:[$rootScope:infdig] 10 $digest() 达到了迭代。中止!”
    • 真的帮了我。谢谢!
    【解决方案2】:

    更新

    这是一个 Angular 模块(基于 @InviS 答案),可以在您的 Angular 应用程序中轻松实现此过滤器: filters-inArrayFilter


    这是基于@InviS 答案的角度过滤器方法:

    过滤器应该是这样的:

    .filter('inArray', function($filter){
        return function(list, arrayFilter, element){
            if(arrayFilter){
                return $filter("filter")(list, function(listItem){
                    return arrayFilter.indexOf(listItem[element]) != -1;
                });
            }
        };
    });
    

    其中 list 是您要过滤的列表(此参数默认由 angular 设置),arrayFilter 是您用作过滤器的数组,element 是要在列表中过滤的属性的名称。

    要使用此过滤器,您可以将 ng-repeat 用作:

    <div ng-repeat='letter in letters | inArray:filterBy:"id"'>{{letter.id}}</div>
    

    其中inArray是过滤器,filterBy (这个过滤器的第一个参数) 是要匹配的数组,"id" (第二个参数) 是要匹配的列表元素数组。

    您可以尝试使用角度过滤器方法live example

    【讨论】:

    • 如果我必须过滤多个列怎么办? chaining 会吗?
    • @dreamer 多列是什么意思?
    • @Cyber​​delphos 如果对象键是数字,您将如何过滤?使用 $index?
    • @alphapilgrim 不明白你的问题,你的意思是过滤一个数组?
    • @Cyber​​delphos 大概这也可以用 2 个对象来完成,用另一个过滤一个?正在寻找修改。
    【解决方案3】:

    相当旧,但我需要它,我不得不稍微改变一下。 这是我的过滤器“notInArray”

    app.filter('notInArray', function($filter){
    return function(list, arrayFilter, element){
        if(arrayFilter){
            return $filter("filter")(list, function(listItem){
              for (var i = 0; i < arrayFilter.length; i++) {
                  if (arrayFilter[i][element] == listItem[element])
                      return false;
              }
              return true;
            });
        }
    };
    

    });

    <md-chips ng-model="filter.SelectedValues" md-autocomplete-snap
              md-require-match="true">
          <md-autocomplete
              md-search-text="searchFilterChip"
              md-items="val in filter.Values | notInArray:filter.SelectedValues:'Id'"
              md-item-text="val.Name"
              md-no-cache="true"
              md-min-length="0">
            <span md-highlight-text="searchFilterChip">{{val.Name}}</span>
          </md-autocomplete>
          <md-chip-template>
            {{$chip.Name}}
          </md-chip-template>
      </md-chips>
    

    我认为这可以改进,但在我的情况下不需要。

    希望对某人有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-03
      • 1970-01-01
      相关资源
      最近更新 更多