首页 文章

如何在angularJS中过滤多个值(OR运算)

提问于
浏览
127

我想在角度中使用 filter 并希望过滤多个值,如果它具有其中一个值,则应显示它 .

我有这样的结构:

一个对象 movie ,其属性为 genres ,我想过滤 ActionComedy .

我知道我可以做 filter:({genres: 'Action'} || {genres: 'Comedy'}) ,但如果我想动态过滤该怎么办 . 例如 . filter: variableX

我如何在 $scope 中设置 variableX ,当我有一个类型的数组我必须过滤?

我可以把它构造成一个字符串,然后做 eval() 但我不想使用eval()...

19 回答

  • -15

    在这里创建自定义过滤器可能有点过分,如果您有多个值,则可以传入自定义比较器:

    $scope.selectedGenres = "Action, Drama"; 
    
    $scope.containsComparator = function(expected, actual){  
      return actual.indexOf(expected) > -1;
    };
    

    然后在过滤器中:

    filter:{name:selectedGenres}:containsComparator
    
  • 1

    Angular Or Filter Module

    $filter('orFilter')([{..}, {..} ...], {arg1, arg2, ...}, false)

    这是链接:https://github.com/webyonet/angular-or-filter

  • 11

    我只想创建一个自定义过滤器 . 他们并不那么难 .

    angular.module('myFilters', []).
      filter('bygenre', function() {
        return function(movies,genres) {
          var out = [];
          // Filter logic here, adding matches to the out var.
          return out;
        }
      });
    

    模板:

    <h1>Movies</h1>
    
    <div ng-init="movies = [
              {title:'Man on the Moon', genre:'action'},
              {title:'Meet the Robinsons', genre:'family'},
              {title:'Sphere', genre:'action'}
           ];" />
    <input type="checkbox" ng-model="genrefilters.action" />Action
    
    <input type="checkbox" ng-model="genrefilters.family" />Family
    {{genrefilters.action}}::{{genrefilters.family}} <ul> <li ng-repeat="movie in movies | bygenre:genrefilters">{{movie.title}}: {{movie.genre}}</li> </ul>

    Edit 这里是链接:Creating Angular Filters

    更新:这是一个fiddle,它有我的建议的精确演示 .

  • 6

    您可以使用控制器功能进行过滤 .

    function MoviesCtrl($scope) {
    
        $scope.movies = [{name:'Shrek', genre:'Comedy'},
                         {name:'Die Hard', genre:'Action'},
                         {name:'The Godfather', genre:'Drama'}];
    
        $scope.selectedGenres = ['Action','Drama'];
    
        $scope.filterByGenres = function(movie) {
            return ($scope.selectedGenres.indexOf(movie.genre) !== -1);
        };
    
    }
    

    HTML:

    <div ng-controller="MoviesCtrl">
        <ul>
            <li ng-repeat="movie in movies | filter:filterByGenres">
                {{ movie.name }} {{ movie.genre }}
            </li>
        </ul>
    </div>
    
  • 1

    这是自定义过滤器的实现,它将使用值数组过滤数据 . 它将支持具有数组和单个键值的多个键对象 . 如上所述inangularJS API AngularJS filter Doc支持具有单个值的多个键过滤器,但是下面的自定义过滤器将支持与angularJS相同的功能,并且还支持值数组以及数组和单个键组合的组合 . 请在下面找到代码片段,

    myApp.filter('filterMultiple',['$filter',function ($filter) {
    return function (items, keyObj) {
        var filterObj = {
            data:items,
            filteredData:[],
            applyFilter : function(obj,key){
                var fData = [];
                if (this.filteredData.length == 0)
                    this.filteredData = this.data;
                if (obj){
                    var fObj = {};
                    if (!angular.isArray(obj)){
                        fObj[key] = obj;
                        fData = fData.concat($filter('filter')(this.filteredData,fObj));
                    } else if (angular.isArray(obj)){
                        if (obj.length > 0){
                            for (var i=0;i<obj.length;i++){
                                if (angular.isDefined(obj[i])){
                                    fObj[key] = obj[i];
                                    fData = fData.concat($filter('filter')(this.filteredData,fObj));    
                                }
                            }
    
                        }
                    }
                    if (fData.length > 0){
                        this.filteredData = fData;
                    }
                }
            }
        };
        if (keyObj){
            angular.forEach(keyObj,function(obj,key){
                filterObj.applyFilter(obj,key);
            });
        }
        return filterObj.filteredData;
    }
    }]);
    

    Usage:

    arrayOfObjectswithKeys | filterMultiple:{key1:['value1','value2','value3',...etc],key2:'value4',key3:[value5,value6,...etc]}
    

    这是一个小提琴示例,实现了上面的 "filterMutiple" 自定义过滤器 . :::Fiddle Example:::

  • 9

    如果你想过滤对象阵列,你可以给

    filter:({genres: 'Action', key :value }.

    个别属性将通过为该属性指定的特定过滤器进行过滤 .

    但是如果您想要通过单个属性过滤并对所有属性进行全局过滤,那么您可以执行类似这样的操作 .

    <tr ng-repeat="supp in $data | filter : filterObject |  filter : search">
    

    其中"filterObject"是用于搜索单个属性的对象,"Search"将在全局搜索每个属性 .

    〜阿图尔

  • 17

    我've spent some time on it and thanks to @chrismarx, I saw that angular'的默认值 filterFilter 允许您传递自己的比较器 . 这是多个值的编辑比较器:

    function hasCustomToString(obj) {
            return angular.isFunction(obj.toString) && obj.toString !== Object.prototype.toString;
      }
      var comparator = function (actual, expected) {
        if (angular.isUndefined(actual)) {
          // No substring matching against `undefined`
          return false;
        }
        if ((actual === null) || (expected === null)) {
          // No substring matching against `null`; only match against `null`
          return actual === expected;
        }
        // I edited this to check if not array
        if ((angular.isObject(expected) && !angular.isArray(expected)) || (angular.isObject(actual) && !hasCustomToString(actual))) {
          // Should not compare primitives against objects, unless they have custom `toString` method
          return false;
        }
        // This is where magic happens
        actual = angular.lowercase('' + actual);
        if (angular.isArray(expected)) {
          var match = false;
          expected.forEach(function (e) {
            e = angular.lowercase('' + e);
            if (actual.indexOf(e) !== -1) {
              match = true;
            }
          });
          return match;
        } else {
          expected = angular.lowercase('' + expected);
          return actual.indexOf(expected) !== -1;
        }
      };
    

    如果我们想为DRY制作自定义过滤器:

    angular.module('myApp')
        .filter('filterWithOr', function ($filter) {
          var comparator = function (actual, expected) {
            if (angular.isUndefined(actual)) {
              // No substring matching against `undefined`
              return false;
            }
            if ((actual === null) || (expected === null)) {
              // No substring matching against `null`; only match against `null`
              return actual === expected;
            }
            if ((angular.isObject(expected) && !angular.isArray(expected)) || (angular.isObject(actual) && !hasCustomToString(actual))) {
              // Should not compare primitives against objects, unless they have custom `toString` method
              return false;
            }
            console.log('ACTUAL EXPECTED')
            console.log(actual)
            console.log(expected)
    
            actual = angular.lowercase('' + actual);
            if (angular.isArray(expected)) {
              var match = false;
              expected.forEach(function (e) {
                console.log('forEach')
                console.log(e)
                e = angular.lowercase('' + e);
                if (actual.indexOf(e) !== -1) {
                  match = true;
                }
              });
              return match;
            } else {
              expected = angular.lowercase('' + expected);
              return actual.indexOf(expected) !== -1;
            }
          };
          return function (array, expression) {
            return $filter('filter')(array, expression, comparator);
          };
        });
    

    然后我们可以在任何我们想要的地方使用它:

    $scope.list=[
      {name:'Jack Bauer'},
      {name:'Chuck Norris'},
      {name:'Superman'},
      {name:'Batman'},
      {name:'Spiderman'},
      {name:'Hulk'}
    ];
    
    
    <ul>
      <li ng-repeat="item in list | filterWithOr:{name:['Jack','Chuck']}">
        {{item.name}}
      </li>
    </ul>
    

    最后这是一个plunkr .

    注意:预期数组应该只包含简单对象,如 StringNumber 等 .

  • 77

    你可以使用angular.filter的searchField过滤器

    JS:

    $scope.users = [
     { first_name: 'Sharon', last_name: 'Melendez' },
     { first_name: 'Edmundo', last_name: 'Hepler' },
     { first_name: 'Marsha', last_name: 'Letourneau' }
    ];
    

    HTML:

    <input ng-model="search" placeholder="search by full name"/> 
    <th ng-repeat="user in users | searchField: 'first_name': 'last_name' | filter: search">
      {{ user.first_name }} {{ user.last_name }}
    </th>
    <!-- so now you can search by full name -->
    
  • 4

    如果情况允许,您也可以使用 ngIf

    <div ng-repeat="p in [
     { name: 'Justin' }, 
     { name: 'Jimi' }, 
     { name: 'Bob' }
     ]" ng-if="['Jimi', 'Bob'].indexOf(e.name) > -1">
     {{ p.name }} is cool
    </div>
    
  • 22

    我发现最快的解决方案是使用angular-filter中的 filterBy 过滤器,例如:

    <input type="text" placeholder="Search by name or genre" ng-model="ctrl.search"/>   
    <ul>
      <li ng-repeat="movie in ctrl.movies | filterBy: ['name', 'genre']: ctrl.search">
        {{movie.name}} ({{movie.genre}}) - {{movie.rating}}
      </li>
    </ul>
    

    好处是angular-filter是一个相当受欢迎的库(GitHub上大约2.6k星),它仍然在积极开发和维护,因此将它作为依赖项添加到项目中应该没问题 .

  • 7

    我相信这就是你要找的东西:

    <div>{{ (collection | fitler1:args) + (collection | filter2:args) }}</div>
    
  • 1

    请试试这个

    var m = angular.module('yourModuleName');
    m.filter('advancefilter', ['$filter', function($filter){
        return function(data, text){
            var textArr = text.split(' ');
            angular.forEach(textArr, function(test){
                if(test){
                      data = $filter('filter')(data, test);
                }
            });
            return data;
        }
    }]);
    
  • 2

    让我们假设您有两个数组,一个用于电影,一个用于流派

    只需使用过滤器: filter:{genres: genres.type}

    这里类型和类型的流派具有流派的 Value

  • 1

    我写了这个字符串和功能(我知道这不是问题,但我搜索它并到达这里),也许它可以扩展 .

    String.prototype.contains = function(str) {
      return this.indexOf(str) != -1;
    };
    
    String.prototype.containsAll = function(strArray) {
      for (var i = 0; i < strArray.length; i++) {
        if (!this.contains(strArray[i])) {
          return false;
        }
      }
      return true;
    }
    
    app.filter('filterMultiple', function() {
      return function(items, filterDict) {
        return items.filter(function(item) {
          for (filterKey in filterDict) {
            if (filterDict[filterKey] instanceof Array) {
              if (!item[filterKey].containsAll(filterDict[filterKey])) {
                return false;
              }
            } else {
              if (!item[filterKey].contains(filterDict[filterKey])) {
                return false;
              }
            }
          }
          return true;
        });  
      };
    });
    

    用法:

    <li ng-repeat="x in array | filterMultiple:{key1: value1, key2:[value21, value22]}">{{x.name}}</li>
    
  • 1

    我有类似的情况 . 编写自定义过滤器对我有用 . 希望这可以帮助!

    JS:

    App.filter('searchMovies', function() {
        return function (items, letter) {
            var resulsts = [];
            var itemMatch = new RegExp(letter, 'i');
            for (var i = 0; i < items.length; i++) {
                var item = items[i];
                if ( itemMatch.test(item.name) || itemMatch.test(item.genre)) {
                    results.push(item);
                }
            }
            return results;
        };
    });
    

    HTML:

    <div ng-controller="MoviesCtrl">
        <ul>
            <li ng-repeat="movie in movies | searchMovies:filterByGenres">
                {{ movie.name }} {{ movie.genre }}
            </li>
        </ul>
    </div>
    
  • -3

    这是我的示例如何为表jsfiddle创建过滤器和指令

    指令获取列表(数据)并使用过滤器创建表

    <div ng-app="autoDrops" ng-controller="HomeController">
    <div class="row">
        <div class="col-md-12">
            <h1>{{title}}</h1>
            <ng-Multiselect array-List="datas"></ng-Multiselect>
        </div>
    </div>
    </div>
    

    我很高兴,如果我帮助你

  • 6

    参加聚会太晚了,但也许可以帮助某人:

    我们可以分两步完成,首先按第一个属性过滤,然后通过第二个过滤器连接:

    $scope.filterd = $filter('filter')($scope.empList, { dept: "account" });
    $scope.filterd = $scope.filterd.concat($filter('filter')($scope.empList, { dept: "sales" }));
    

    See the working fiddle with multiple property filter

  • 2

    我的解决方案

    ng-repeat="movie in movies | filter: {'Action'} + filter: {'Comedy}"
    
  • 81

    最好的答案是:

    filter:({genres: 'Action', genres: 'Comedy'}
    

相关问题