Javascript 如何在angularJS中过滤多个值(或操作)

Javascript 如何在angularJS中过滤多个值(或操作),javascript,angularjs,angularjs-ng-repeat,Javascript,Angularjs,Angularjs Ng Repeat,我想在angular中使用过滤器,并想过滤多个值,如果它有一个值,那么应该显示它 例如,我有以下结构: 一个对象movie,它具有属性genres,我想过滤动作和喜剧 我知道我可以做过滤:({genres:'Action'}|{genres:'committee'}),但是如果我想动态过滤它,该怎么办呢。例如,filter:variableX 当我有一个必须过滤的类型数组时,如何在$scope中设置variableX 我可以将它构造为一个字符串,然后执行一个eval(),但我不想使用eval()

我想在angular中使用
过滤器
,并想过滤多个值,如果它有一个值,那么应该显示它

例如,我有以下结构:

一个对象
movie
,它具有属性
genres
,我想过滤
动作
喜剧

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

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


我可以将它构造为一个字符串,然后执行一个
eval()
,但我不想使用eval()…

我只想创建一个自定义过滤器。他们没有那么难

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

家庭
{{genrefilters.action}::{{genrefilters.family}
  • {{movie.title}:{{{movie.genre}
编辑以下是链接:


更新:这里有一个我的建议的精确演示。

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

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:


  • {{movie.name}{{movie.genre}

在这里创建自定义过滤器可能有些过分,如果您有如下倍数值,您可以传入一个自定义比较器:

$scope.selectedGenres = "Action, Drama"; 

$scope.containsComparator = function(expected, actual){  
  return actual.indexOf(expected) > -1;
};
然后在过滤器中:

filter:{name:selectedGenres}:containsComparator

这是自定义筛选器的实现,它将使用值数组对数据进行筛选。它将支持具有数组和单个值键的多个键对象。正如GularJS API中提到的,支持单值多键过滤器,但下面的自定义过滤器将支持与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;
}
}]);
下面是一个fiddle示例,它实现了上面的“filterMutiple”自定义过滤器。 最好的答案是:

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

我相信这就是你想要的:

<div>{{ (collection | fitler1:args) + (collection | filter2:args) }}</div>
{(集合| fitler1:args)+(集合|过滤器2:args)}

您可以使用

JS:

arrayOfObjectswithKeys | filterMultiple:{key1:['value1','value2','value3',...etc],key2:'value4',key3:[value5,value6,...etc]}
$scope.users = [
 { first_name: 'Sharon', last_name: 'Melendez' },
 { first_name: 'Edmundo', last_name: 'Hepler' },
 { first_name: 'Marsha', last_name: 'Letourneau' }
];
<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 -->
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:

arrayOfObjectswithKeys | filterMultiple:{key1:['value1','value2','value3',...etc],key2:'value4',key3:[value5,value6,...etc]}
$scope.users = [
 { first_name: 'Sharon', last_name: 'Melendez' },
 { first_name: 'Edmundo', last_name: 'Hepler' },
 { first_name: 'Marsha', last_name: 'Letourneau' }
];
<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 -->
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;
    };
});

{{user.first_name}{{user.last_name}}

如果要对对象数组进行筛选,则可以

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

单个属性将通过为该属性指定的特定筛选器进行筛选

但是,如果您想按单个属性进行过滤,并对所有属性进行全局过滤,那么您可以这样做。
我写这篇文章是为了字符串和功能(我知道这不是问题,但我在这里搜索了它),也许它可以扩展

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;
    });  
  };
});
String.prototype.contains=函数(str){
返回这个。indexOf(str)!=-1;
};
String.prototype.containsAll=函数(strArray){
对于(变量i=0;i
用法:

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

  • 角度或过滤模块

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


    下面是链接:

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

    只需将筛选器用作:
    筛选器:{genres:genres.type}

    这里,作为数组和类型的类型对类型有价值

    我的解决方案

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

    我花了一些时间在上面,多亏了@chrismarx,我看到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;
        }
      };
    
    如果我们想为干式过滤器定制:

    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>
    
    $scope.list=[
    {姓名:'Jack Bauer'},
    {姓名:'Chuck Norris'},
    {姓名:'超人'},
    {姓名:'蝙蝠侠'},
    {name:'Spiderman'},
    {name:'Hulk'}
    ];
    
    • {{item.name}
    最后是一个例子

    注意:预期的数组应该只包含简单的对象,如字符串数字等。

    请尝试此操作

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

    我也遇到过类似的情况。编写自定义过滤器对我很有用。希望这对我有所帮助

    JS:

    arrayOfObjectswithKeys | filterMultiple:{key1:['value1','value2','value3',...etc],key2:'value4',key3:[value5,value6,...etc]}
    
    $scope.users = [
     { first_name: 'Sharon', last_name: 'Melendez' },
     { first_name: 'Edmundo', last_name: 'Hepler' },
     { first_name: 'Marsha', last_name: 'Letourneau' }
    ];
    
    <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 -->
    
    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;
        };
    });
    
    App.filter('searchMovies',function(){
    返回函数(项目、字母){
    var results=[];
    var itemMatch=new RegExp(字母“i”);
    对于(变量i=0;i
    HTML:

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

    如果情况允许,您也可以使用
    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>
    
    
    {{p.name}}很酷
    
    以下是我如何为表创建筛选器和指令的示例

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

    <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>