Cómo filtrar múltiples valores (operación O) en angularJS

Resuelto justGoscha asked hace 11 años • 20 respuestas

Quiero usar filterangular y quiero filtrar por múltiples valores, si tiene alguno de los valores, entonces debería mostrarse.

Tengo por ejemplo esta estructura:

Un objeto movieque tiene la propiedad genresy quiero filtrar por Actiony Comedy.

Sé que puedo hacerlo filter:({genres: 'Action'} || {genres: 'Comedy'}), pero qué hacer si quiero filtrarlo dinámicamente. P.ejfilter: variableX

¿Cómo configuro variableXcuando $scopetengo una variedad de géneros que tengo que filtrar?

Podría construirlo como una cadena y luego hacer un eval()pero no quiero usar eval()...

justGoscha avatar Apr 08 '13 04:04 justGoscha
Aceptado

Simplemente crearía un filtro personalizado. No son tan difíciles.

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

plantilla:

<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
<br />
<input type="checkbox" ng-model="genrefilters.family" />Family
<br />{{genrefilters.action}}::{{genrefilters.family}}
<ul>
    <li ng-repeat="movie in movies | bygenre:genrefilters">{{movie.title}}: {{movie.genre}}</li>
</ul>

Edite aquí está el enlace: Creación de filtros angulares

ACTUALIZACIÓN : Aquí hay un violín que tiene una demostración exacta de mi sugerencia.

Xesued avatar Apr 08 '2013 00:04 Xesued

Puede utilizar una función de controlador para filtrar.

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>
jlareau avatar Apr 08 '2013 00:04 jlareau

Crear un filtro personalizado puede ser excesivo aquí, simplemente puede pasar un comparador personalizado, si tiene valores múltiplos como:

$scope.selectedGenres = "Action, Drama"; 

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

luego en el filtro:

filter:{name:selectedGenres}:containsComparator
chrismarx avatar Sep 03 '2013 14:09 chrismarx

Aquí está la implementación del filtro personalizado, que filtrará los datos utilizando una matriz de valores. Admitirá múltiples objetos clave con una matriz y un valor único de claves. Como se mencionó en el filtro AngularJS API de inangularJS, Doc admite filtros de claves múltiples con un solo valor, pero el filtro personalizado a continuación admitirá la misma característica que angularJS y también admite una matriz de valores y una combinación de matrices y valores únicos de claves. Encuentre el fragmento de código a continuación.

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

Uso:

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

Aquí hay un ejemplo de violín con la implementación del filtro personalizado "filterMutiple" anterior . :::Ejemplo de violín:::

Nirmal Kumar VeluPillai avatar Jan 16 '2014 18:01 Nirmal Kumar VeluPillai