Fonction de filtre personnalisé AngularJS

91

À l'intérieur de ma manette, je voudrais filtrer un tableau d'objets. Chacun de ces objets est une carte qui peut contenir des chaînes ainsi que des listes

J'ai essayé d'utiliser le $filter('filter')(array, function)format mais je ne sais pas comment accéder aux éléments individuels du tableau dans ma fonction. Voici un extrait pour montrer ce que je veux.

$filter('filter')(array, function() {
  return criteriaMatch(item, criteria);
});

Et puis dans le criteriaMatch(), je vérifierai si chacune des propriétés individuelles correspond

var criteriaMatch = function(item, criteria) {
  // go thro each individual property in the item and criteria
  // and check if they are equal
}

Je dois faire tout cela dans le contrôleur et compiler une liste de listes et les définir dans la portée. J'ai donc besoin d'accéder $filter('filter')uniquement de cette manière. Tous les exemples que j'ai trouvés sur le net jusqu'à présent ont des recherches de critères statiques dans la fonction, ils ne passent pas un objet de critères et ne testent pas chaque élément du tableau.

user2368436
la source
3
Pourquoi avez-vous besoin d'un filtre? Les filtres sont généralement utilisés à partir de modèles. Ne pouvez-vous pas simplement avoir une fonction simple dans votre contrôleur si vous ne l'utilisez qu'à partir de là?
Ketan
au lieu d'aller manuellement dans chaque élément du tableau, j'ai pensé que nous pourrions utiliser la fonctionnalité $ filter ('filter') d'angular (qui se chargera d'itérer chaque élément si nous
spécifions

Réponses:

173

Vous pouvez l'utiliser comme ceci: http://plnkr.co/edit/vtNjEgmpItqxX5fdwtPi?p=preview

Comme vous l'avez trouvé, filteraccepte la fonction de prédicat qui accepte élément par élément du tableau. Il vous suffit donc de créer une fonction de prédicat basée sur le donné criteria.

Dans cet exemple, criteriaMatchest une fonction qui renvoie une fonction de prédicat qui correspond à la donnée criteria.

modèle:

<div ng-repeat="item in items | filter:criteriaMatch(criteria)">
  {{ item }}
</div>

portée:

$scope.criteriaMatch = function( criteria ) {
  return function( item ) {
    return item.name === criteria.name;
  };
};
Tosh
la source
Je n'emploierai pas cette fonction de critèreMatch du html .. comment vais-je l'appeler de l'intérieur du contrôleur est-ce correct? $ filter ('filtre') (tableau, fonction () {return critèreMatch (élément, critères);});
user2368436
6
Si vous ne l'utilisez pas dans votre modèle, la définition du filtre ne vous donne aucun avantage. Vous pouvez simplement définir une simple fonction javascript, car elle y est encore plus courte. Vous pouvez utiliser la filterméthode native dans l'objet Array:array.filter(function(item){return item.name === criteria.name;})
Tosh
J'ai une fonction javascript. Je voulais juste m'assurer que angular n'avait pas un moyen plus facile de le faire .. j'accepterai votre réponse. THX.
user2368436
2

Voici un exemple de la façon dont vous utiliseriez filterdans votre JavaScript AngularJS (plutôt que dans un élément HTML).

Dans cet exemple, nous avons un tableau d'enregistrements Pays, chacun contenant un nom et un code ISO à 3 caractères.

Nous voulons écrire une fonction qui recherchera dans cette liste un enregistrement correspondant à un code spécifique à 3 caractères.

Voici comment procéder sans utiliser filter:

$scope.FindCountryByCode = function (CountryCode) {
    //  Search through an array of Country records for one containing a particular 3-character country-code.
    //  Returns either a record, or NULL, if the country couldn't be found.
    for (var i = 0; i < $scope.CountryList.length; i++) {
        if ($scope.CountryList[i].IsoAlpha3 == CountryCode) {
            return $scope.CountryList[i];
        };
    };
    return null;
};

Oui, rien de mal à ça.

Mais voici à quoi ressemblerait la même fonction, en utilisant filter:

$scope.FindCountryByCode = function (CountryCode) {
    //  Search through an array of Country records for one containing a particular 3-character country-code.
    //  Returns either a record, or NULL, if the country couldn't be found.

    var matches = $scope.CountryList.filter(function (el) { return el.IsoAlpha3 == CountryCode; })

    //  If 'filter' didn't find any matching records, its result will be an array of 0 records.
    if (matches.length == 0)
        return null;

    //  Otherwise, it should've found just one matching record
    return matches[0];
};

Beaucoup plus soigné.

N'oubliez pas que filterrenvoie un tableau comme résultat (une liste d'enregistrements correspondants), donc dans cet exemple, nous voulons soit retourner 1 enregistrement, soit NULL.

J'espère que cela t'aides.

Mike Gledhill
la source
0

De plus, si vous souhaitez utiliser le filtre dans votre contrôleur de la même manière que vous le faites ici:

<div ng-repeat="item in items | filter:criteriaMatch(criteria)">
  {{ item }}
</div>

Vous pouvez faire quelque chose comme:

var filteredItems =  $scope.$eval('items | filter:filter:criteriaMatch(criteria)');
cafesanu
la source
6
Alternativement,var filteredItems = $filter('criteriaMatch')(items, criteria);
321zeno