136 votes

Comment filtrer plusieurs valeurs (opération OR) en angularJS

Je veux utiliser le filter en angulaire et je veux filtrer pour plusieurs valeurs, si elle a l'une ou l'autre des valeurs alors elle doit être affichée.

J'ai par exemple cette structure :

Un objet movie qui a la propriété genres et je veux filtrer pour Action y Comedy .

Je sais que je peux faire filter:({genres: 'Action'} || {genres: 'Comedy'}) mais que faire si je veux le filtrer dynamiquement. Par exemple filter: variableX

Comment puis-je régler variableX dans le $scope quand j'ai un tableau des genres que je dois filtrer ?

Je pourrais le construire comme une chaîne et ensuite faire un eval() mais je ne veux pas utiliser eval()...

17 votes

Vous êtes sûr que filter:({genres: 'Action'} || {genres: 'Comedy'}) fonctionne même ? il ne fonctionne pas dans angular 1.3.16 .

4 votes

Même chose pour la 1.4.8 ! ça ne marche pas ^^.

88voto

Xesued Points 2139

Je créerais simplement un filtre personnalisé. Ce n'est pas si difficile.

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

modèle :

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

Modifier Voici le lien : Création de filtres Angular

UPDATE : Voici un violon qui a une démo exacte de ma suggestion.

0 votes

Donc, dans la sortie, je renvoie les objets vidéo que je veux afficher ?

0 votes

Désolé, j'ai mis du temps à revenir. J'ai mis à jour ma réponse avec un bricolage d'un exemple concret.

0 votes

Ok, merci, en attendant j'ai trouvé la solution moi-même, mais cela aidera sûrement quelqu'un plus tard :)

82voto

jlareau Points 1054

Vous pouvez utiliser une fonction de contrôleur pour filtrer.

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 votes

Outre la séparation des préoccupations, y a-t-il une raison (en termes de performances) pour laquelle cela serait évité ?

1 votes

Version javascript si d'autres personnes la recherchent : $scope.filteredMovies = $filter('filter')($scope.movies, $scope.filterByGenres);

24voto

chrismarx Points 1381

La création d'un filtre personnalisé peut être inutile ici, vous pouvez simplement passer dans un comparateur personnalisé, si vous avez les valeurs multiples comme :

$scope.selectedGenres = "Action, Drama"; 

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

puis dans le filtre :

filter:{name:selectedGenres}:containsComparator

1 votes

Cela m'a beaucoup aidé. Merci

0 votes

@chrismarx Qu'est-ce que le ng-model dans le fichier de vue pour le lier au filtre décrit ? (J'aime la simplicité de votre réponse et j'essaie de la faire fonctionner, mais je ne sais pas comment étiqueter mon fichier de vue. <input> 's ng-model . :)

0 votes

18voto

Voici l'implémentation d'un filtre personnalisé, qui filtrera les données en utilisant un tableau de valeurs, et qui supportera un objet à clés multiples avec un tableau et une seule valeur de clés. Comme mentionné dans l'API inangularJS Doc sur les filtres AngularJS supporte le filtre à clés multiples avec une seule valeur, mais le filtre personnalisé ci-dessous supportera la même fonctionnalité qu'angularJS et supportera également le tableau de valeurs et la combinaison de tableau et de valeur unique de clés,

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

Utilisation :

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

Voici un exemple de bidouille avec l'implémentation de ce qui précède. "filterMutiple" filtre personnalisé. :::Exemple de violon :: :

1 votes

Vous semblez avoir l'intention correcte mais votre exemple ne semble pas fonctionner comme prévu. La sortie dans le tableau semble plutôt incohérente.

0 votes

Cela ne fonctionne pas avec les JSON contenant des objets imbriqués. L'idéal aurait été que cela fonctionne. length property undefined erreur dans la console.

0 votes

Cela fonctionne pour moi mais il retourne tous les résultats s'il ne trouve pas l'attribut recherché dans la liste, comment puis-je faire pour inverser ce comportement et ne retourner aucun résultat si la valeur n'existe pas dans la liste ?

15voto

user1941574 Points 1

Si vous voulez filtrer sur un tableau d'objets, vous pouvez utiliser la commande suivante

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

La propriété individuelle sera filtrée par le filtre particulier donné pour cette propriété.

Mais si vous voulez filtrer par propriété individuelle et filtrer globalement pour toutes les propriétés, vous pouvez faire quelque chose comme ceci.

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

Où "filterObject" est un objet pour rechercher une propriété individuelle et "Search" recherchera dans chaque propriété globalement.

~Atul

0 votes

Cela a bien fonctionné pour moi et c'était une meilleure solution que d'autres qui suggéraient de décharger le filtrage dans une fonction, car AngularJS fait des correspondances de texte partiel lorsqu'il filtre sur des chaînes de caractères.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X