angular ng-repeat ignore un élément s'il correspond à une expression

91

Je cherche un moyen de dire à angular de sauter un élément dans un ng-repeat s'il correspond à une expression, en gros continue;

Dans le contrôleur:

$scope.players = [{
    name_key:'FirstPerson', first_name:'First', last_name:'Person'
}, {
    name_key:'SecondPerson', first_name:'Second', last_name:'Person'
}]

Maintenant, dans mon modèle, je veux montrer à tous ceux qui ne correspondent pas name_key='FirstPerson'. J'ai pensé que ce devait être des filtres, alors j'ai configuré un Plunkr pour jouer avec mais je n'ai pas eu de chance. Tentative de Plunkr

aron.duby
la source
J'essaie de comprendre: voulez-vous afficher tous les éléments, mais indiquez qui correspondent et qui ne l'est pas? ou simplement filtrer?
Maxim Shoustin

Réponses:

144

Comme @Maxim Shoustin l'a suggéré, la meilleure façon d'obtenir ce que vous voulez serait d'utiliser un filtre personnalisé.
Mais il y a d'autres moyens, l'un d'eux étant d'utiliser la ng-ifdirective sur le même élément où vous avez mis la ng-repeatdirective (aussi, voici le plunker ):

<ul>
    <li ng-repeat="player in players" ng-if="player.name_key!='FirstPerson'"></li>
</ul>

Cela peut présenter un inconvénient mineur d'un point de vue esthétique, mais présente un avantage majeur en ce que votre filtrage pourrait être basé sur une règle qui n'est pas aussi étroitement couplée au playerstableau et qui peut facilement accéder à d'autres données dans la portée de votre application:

  <li 
      ng-repeat="player in players" 
      ng-if="app.loggedIn && player.name != user.name"
  ></li>

Mise à jour
Comme indiqué, c'est l' une des solutions à ce type de problème et peut ou non répondre à vos besoins.
Comme indiqué dans les commentaires, il ng-ifs'agit d'une directive, ce qui signifie en fait qu'elle pourrait faire plus de choses en arrière-plan que vous ne le pensez.
Par exemple, ng-if crée une nouvelle étendue à partir de son parent :

La portée créée dans ngIf hérite de sa portée parente à l'aide de l'héritage prototypique.

Cela n'affecte généralement pas le comportement normal, mais pour éviter les cas inattendus, vous devez garder cela à l'esprit avant de l'implémenter.

gion_13
la source
c'était exactement ce que je cherchais, je savais qu'il devait y avoir un moyen court et doux de le faire sans le filtre personnalisé. Merci!
aron.duby
Remarque: certains comportements de portée de ng-if peuvent être délicats. J'ai essayé cette méthode et cela a causé des problèmes ailleurs. A savoir, j'ai une directive "watcher" qui diffuse un événement lorsque le répéteur est terminé. Après avoir ajouté le ng-if à ce répéteur, il n'a plus déclenché cet événement. Un filtre personnalisé pourrait en fait être la solution la plus propre.
claywhipkey
@claywhipkey vous avez raison, le moyen le plus propre est d'utiliser un filtre, mais cela ne convient pas à tous les cas. Quoi qu'il en soit, thx pour le commentaire et vous pouvez voir que j'ai ajouté heads - up mise à jour dans la réponse juste pour faire toute personne au courant des conséquences de l' utilisation d' une directive pour filtrer les données.
gion_13
43

Je sais que c'est un ancien, mais au cas où quelqu'un chercherait une autre solution possible, voici une autre façon de résoudre ce problème - utilisez la fonctionnalité de filtre standard :

Objet: un objet modèle peut être utilisé pour filtrer des propriétés spécifiques sur des objets contenus par tableau. Par exemple, le prédicat {name: "M", phone: "1"} renverra un tableau d'éléments dont le nom de propriété contient "M" et le numéro de téléphone de propriété "1". ... Le prédicat peut être annulé en préfixant la chaîne avec!. Par exemple, le prédicat {name: "! M"} retournera un tableau d'éléments dont le nom de propriété ne contient pas "M".

Donc, pour l'exemple TS, quelque chose comme ça devrait faire:

<ul>
    <li ng-repeat="player in players | filter: { name_key: '!FirstPerson' }"></li>
</ul>

Pas besoin d'écrire des filtres personnalisés, pas besoin d'utiliser ng-ifavec sa nouvelle portée.

Ilya Luzyanin
la source
Simple au point. Aucun filtre personnalisé ou nouvelle portée créé comme l'auteur l'a indiqué. Parfait pour sauter une seule valeur dans une liste.
mbokil
Je pense que vous devez omettre le 'player' de 'player.name_key' - donc ce serait juste "{name_key: '! FirstPerson'}" dans l'exemple ci-dessus.
smithml
Je n'ai jamais pu faire en sorte qu'Angular joue bien avec des touches vides. Existe-t-il une sorte d'astuce pour utiliser les filtres intégrés pour l'équivalent de player in players | filter: { name_key: '' }? Cette directive particulière ne correspondra pas uniquement aux joueurs sans / un vide name_key. L'inverse, name_key: '!'destiné à sélectionner n'importe quel joueur avec un non-vide name_keyne fonctionnera pas non plus.
Eric L.
Vous pouvez vérifier cette réponse.
Ilya Luzyanin
4
Attention, cela ne fonctionne qu'avec des tableaux, pas avec des propriétés d'objet dans un cas tel queng-repeat="(key, val) in player"
David Diez
19

Vous pouvez utiliser un filtre personnalisé lorsque vous implémentez ng-repeat. Quelque chose comme:

 data-ng-repeat="player in players |  myfilter:search.name

myfilter.js:

app.filter('myfilter', function() {


   return function( items, name) {
    var filtered = [];

    angular.forEach(items, function(item) {

      if(name == undefined || name == ''){
        filtered.push(item);
        }

      /* only if you want start With*/
      // else if(item.name_key.substring(0, name.length) !== name){
      //   filtered.push(item);
      // }

      /* if you want contains*/
      // else if(item.name_key.indexOf(name) < 0 ){
      //   filtered.push(item);
      // }

       /* if you want match full name*/
       else if(item.name_key !== name ){
        filtered.push(item);
      }
    });

    return filtered;
  };
});

Démo Plunker

Maxim Shoustin
la source
Merci pour le travail que vous y consacrez. C'est tout à fait correct, mais j'ai fini par utiliser la facilité de réponse @ gion_13 dans le code, alors j'ai pensé que je ferais mieux de marquer sa réponse comme acceptée
aron.duby