kątowe ng-powtarzanie pomija element, jeśli pasuje do wyrażenia

91

Szukam sposobu, aby w zasadzie powiedzieć Angularowi, aby pominął element w powtórzeniu ng, jeśli pasuje do wyrażenia, w zasadzie continue;

W kontrolerze:

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

Teraz w moim szablonie chcę pokazać wszystkim, którzy nie pasują name_key='FirstPerson'. Pomyślałem, że to filtry, więc skonfigurowałem Plunkra, aby się nim bawić, ale nie miałem szczęścia. Plunkr Attempt

aron.duby
źródło
Próbuję zrozumieć: czy chcesz pokazać wszystkie przedmioty, ale wskazać, kto pasuje, a kto nie? czy po prostu przefiltruj?
Maxim Shoustin

Odpowiedzi:

144

Jak zasugerował @Maxim Shoustin , najlepszym sposobem osiągnięcia tego, co chcesz, byłoby użycie niestandardowego filtra.
Ale są też inne sposoby, jednym z nich jest użycie ng-ifdyrektywy w tym samym elemencie, w którym umieściłeś ng-repeatdyrektywę (również, tutaj jest plunker ):

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

Z estetycznego punktu widzenia może to stanowić niewielką wadę, ale ma tę główną zaletę, że filtrowanie może opierać się na regule, która nie jest tak ściśle powiązana z playerstablicą i może łatwo uzyskać dostęp do innych danych w zakresie aplikacji:

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

Aktualizacja
Jak wspomniano, jest to jedno z rozwiązań tego rodzaju problemu i może, ale nie musi, odpowiadać Twoim potrzebom.
Jak wskazano w komentarzach, ng-ifjest to dyrektywa, co w rzeczywistości oznacza, że ​​może zrobić więcej rzeczy w tle, niż można by się spodziewać.
Na przykład ng-if tworzy nowy zakres z jego rodzica :

Zakres utworzony w ngIf dziedziczy po swoim zakresie nadrzędnym przy użyciu dziedziczenia prototypowego.

Zwykle nie wpływa to na normalne zachowanie, ale aby zapobiec nieoczekiwanym przypadkom, należy o tym pamiętać przed wdrożeniem.

gion_13
źródło
to było dokładnie to, czego szukałem, wiedziałem, że musi być jakiś krótki i słodki sposób na zrobienie tego bez niestandardowego filtra. Dzięki!
aron.duby,
Uwaga: istnieją pewne zachowania zakresu ng-if, które mogą być trudne. Wypróbowałem tę metodę i spowodowało to problemy w innych miejscach. Mianowicie mam dyrektywę "watcher", która nadaje zdarzenie, gdy repeater jest skończony. Po dodaniu ng-if do tego repeatera nie odpalało już tego zdarzenia. Własny filtr może być najczystszym rozwiązaniem.
claywhipkey
@claywhipkey masz rację, najczystszym sposobem jest użycie filtra, ale nie jest to odpowiednie dla wszystkich przypadków. W każdym razie dziękuję za komentarz i widzicie, że dodałem do odpowiedzi aktualizację heads-up, aby każdy był świadomy konsekwencji stosowania dyrektywy do filtrowania danych.
gion_13
43

Wiem, że to stara, ale gdyby ktoś szukał innego możliwego rozwiązania, oto inny sposób rozwiązania tego problemu - użyj standardowej funkcjonalności filtra :

Obiekt: obiekt wzorca może służyć do filtrowania określonych właściwości obiektów zawartych w szyku. Na przykład predykat {name: "M", phone: "1"} zwróci tablicę elementów, których nazwa właściwości zawiera "M", a nazwa właściwości zawiera "1". ... Predykat można zanegować, poprzedzając łańcuch znakiem!. Na przykład predykat {name: "! M"} zwróci tablicę elementów, których nazwa właściwości nie zawiera "M".

Więc dla przykładu TS powinno zrobić coś takiego:

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

Nie ma potrzeby pisania niestandardowych filtrów, nie ma potrzeby używania ng-ifich z nowym zakresem.

Ilya Luzyanin
źródło
Proste do rzeczy. Nie utworzono żadnego filtra niestandardowego ani nowego zakresu, jak stwierdził autor. Idealny do pomijania pojedynczej wartości na liście.
mbokil
Myślę, że musisz pominąć 'player' z 'player.name_key' - więc w powyższym przykładzie będzie to po prostu „{name_key: '! FirstPerson'}”.
smithml
Nigdy nie udało mi się zmusić Angulara do ładnej gry z pustymi klawiszami. Czy jest jakaś sztuczka polegająca na użyciu wbudowanych filtrów jako odpowiednika player in players | filter: { name_key: '' }? Ta konkretna dyrektywa nie będzie dotyczyła tylko graczy bez pustego pola name_key. Odwrotność, która name_key: '!'ma na celu wybranie dowolnego gracza z niepustym, name_keyrównież nie zadziała.
Eric L.,
Możesz sprawdzić odpowiedź.
Ilya Luzyanin
4
Uważaj, to działa tylko z tablicami, a nie z właściwościami obiektów w przypadku takim jakng-repeat="(key, val) in player"
David Diez
19

Podczas implementacji możesz użyć niestandardowego filtru ng-repeat. Coś jak:

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

Próbny Plunker

Maxim Shoustin
źródło
Dzięki za pracę, którą w to włożyłeś. Jest zdecydowanie poprawna, ale skończyło się na łatwości odpowiedzi @ gion_13 w kodzie, więc pomyślałem, że lepiej oznaczyć jego jako zaakceptowaną odpowiedź
aron.duby.