AngularJS ng-repeat uchwyt pusta wielkość liter listy


377

Myślałem, że będzie to bardzo powszechna sprawa, ale nie mogłem znaleźć sposobu, aby sobie z tym poradzić w AngularJS. Załóżmy, że mam listę zdarzeń i chcę wyprowadzić je za pomocą AngularJS, więc to całkiem proste:

<ul>
    <li ng-repeat="event in events">{{event.title}}</li>
</ul>

Ale jak poradzić sobie ze sprawą, gdy lista jest pusta? Chcę mieć okno komunikatu w miejscu, w którym znajduje się lista z napisem „Brak zdarzeń” lub podobnym. Jedyne, co by się zbliżyło, to ng-switchz events.length(jak sprawdzić, czy pusty, gdy obiekt, a nie tablica?), Ale czy to naprawdę jedyna dostępna opcja?


4
Odpowiedź Artema jest dobra (+1). Oto dyskusja grupy google wykorzystująca filtr w celach informacyjnych / porównawczych: groups.google.com/d/topic/angular/wR06cN5oVBQ/discussion
— Mark Rajcok

Odpowiedzi:


569

Możesz użyć ngShow .

<li ng-show="!events.length">No events</li>

Patrz przykład .

Lub możesz użyć ngHide

<li ng-hide="events.length">No events</li>

Patrz przykład .

Dla obiektu możesz przetestować Object.keys .


1
Rzeczywiście @ArtemAndreev. Gdy „zdarzenia” są pustą tablicą, zwraca wartość true, mimo że tablica jest pusta
— Rob Juurlink

Myślę, że jest problem z Object.keys: jsfiddle.net/J9b5z , jak byś sobie z tym poradził?
— Dani

5
nh-show działał w moim przypadku, ale nie aktualizuje stanu, gdy wstawiam filtr i nic nie zwraca. Obiekt pojawia się również przy pierwszym ładowaniu i znika, gdy proces powtarzania jest wykonywany przy ładowaniu strony.
— dvdmn

1
@Dani spróbuj dodać funkcję do kontrolera, który wykonuje test. Następnie możesz po prostu wywołać dyrektywę za pomocą ng-hide="hasEvents()".
— Pan S

Tak, dziękuję. Mam jednak nadzieję, że będzie bardziej elegancki sposób bez „zanieczyszczania” kontrolera.
— Dani

370

A jeśli chcesz użyć tego z filtrowaną listą, oto fajna sztuczka:

<ul>
    <li ng-repeat="item in filteredItems  = (items | filter:keyword)">
        ...
    </li>
</ul>
<div ng-hide="filteredItems.length">No items found</div>

3
Bardzo przydatne. Literówka z „filterFragments”.
— ravishi

1
Słodkie! Jednak wyrażenie w powtórzeniu ng wygląda dziwnie. Czy jest szansa, że ​​mógłbyś to wyjaśnić? Dzięki!!
— MK Safi,

7
@MKSafi, tworzy nową zmienną w wywoływanym zakresie filteredItemsi ustawia jej wartość na (items | filter:keyword)- innymi słowy, tablicę zwróconą przez filtr
— AlexFoxGill

17
TAK! Ninja plus punkty! Oszczędza to kąta od dwukrotnej oceny złożonego filtra!
— markmarijnissen

2
Poza tym wydaje się, że istnieją pewne ograniczenia związane z wieloma filtrami, "face in filteredFaces = faces|filter:{deleted: true} | orderBy:'text'ale zgadzam się ze wszystkimi, to fantastyczna sztuczka.
— Fitter Man

29

Możesz chcieć sprawdzić dyrektywę angular-ui, ui-if jeśli chcesz tylko usunąć ulz DOM, gdy lista jest pusta:

<ul ui-if="!!events.length">
    <li ng-repeat="event in events">{{event.title}}</li>
</ul>

1
Dzięki. Czuje się czystszy niż tylko ukrywanie go.
— Prinzhorn,

@Mortimer: więc w takim przypadku potrzebujemy interfejsu kątowego?
— Shibbir Ahmed

możesz używać ng-hidebez interfejsu kątowego, ale po prostu ukryje on węzeł, nie usunie go z drzewa DOM. Dzięki ui-ifdyrektywie angular-ui usunie węzeł DOM. Musisz więc przynajmniej dodać ui-ifdyrektywę z kodu angular-ui do własnego kodu.
— Mortimer

21
najnowszy kątownik ng-ifzawarł!
— markmarijnissen

4
Zauważ, że ng-iftworzy nowy zakres, gdzie ng-hidenie ma. Może to spowodować nieoczekiwane zachowanie.
— Arnold Daniels

29

W nowszych wersjach angularjs poprawną odpowiedzią na to pytanie jest ng-if:

<ul>
  <li ng-if="list.length === 0">( No items in this list yet! )</li>
  <li ng-repeat="item in list">{{ item }}</li>
</ul>

To rozwiązanie nie będzie migotać, gdy lista ma zostać pobrana, ponieważ lista musi zostać zdefiniowana, a jej długość musi wynosić 0.

Oto plunker, aby pokazać go w użyciu: http://plnkr.co/edit/in7ha1wTlpuVgamiOblS?p=preview

Wskazówka: Możesz także wyświetlić ładujący się tekst lub pokrętło:

  <li ng-if="!list">( Loading... )</li>

23
<ul>
    <li ng-repeat="item in items | filter:keyword as filteredItems">
        ...
    </li>
    <li ng-if="filteredItems.length===0">
        No items found
    </li>
</ul>

Jest to podobne do @Konrad „ktoso” Malawski, ale nieco łatwiejsze do zapamiętania.

Testowane z Angular 1.4


3
Masz na myśling-if='!filteredItems.length'
— abrunet,

Jak to zrobić z wieloma filtrami?
— Jordash,

@Jordash Nadal je potokuj item in items | filter: ... | filter: ...
— Bernard

Ładnym, dalszym dopracowaniem jest<li ng-if="!filteredItems.length">
— Matty J

To jest świetne. Wcześniej stosowałem dużo brudniejszą metodęitem in (filteredItems = (items | filter: someFilter))
— Firze,

6

Oto inne podejście przy użyciu CSS zamiast JavaScript / AngularJS.

CSS:

.emptymsg {
  display: list-item;
}

li + .emptymsg {
  display: none;
}

Narzut:

<ul>
    <li ng-repeat="item in filteredItems"> ... </li>
    <li class="emptymsg">No items found</li>
</ul>

Jeśli lista jest pusta, <li ng-repeat = "item in filterItems"> itp. Zostanie skomentowany i stanie się komentarzem zamiast elementu li.


Pytanie brzmi: „Chcę mieć okno komunikatu w miejscu, w którym znajduje się lista”. Myślę też, że rozdzielenie logiki na arkusz stylów jest niekorzystne. Trudne w utrzymaniu i proszące o kłopoty.
— Prinzhorn,

1
@Prinzhorn, myślę, że korzystanie z CSS jest zaletą, ponieważ logika jest bardzo prosta i łatwa w utrzymaniu, CSS może być wykorzystywany do innych list i nie opiera się na JavaScript. Nie są potrzebne dodatkowe osoby słuchające ani obserwujące. Wiadomość może być stylizowana na pudełko, po prostu nie chciałem, aby odpowiedź była prosta.
— Miriam Salzer

Kilka miesięcy spóźnienia, oczywiście, ale zgadzam się z Miriam, myślę, że ta odpowiedź jest genialna.
— Jon Combe,

2

Możesz użyć tego przełącznika ng:

<div ng-app ng-controller="friendsCtrl">
  <label>Search: </label><input ng-model="searchText" type="text">
  <div ng-init="filtered = (friends | filter:searchText)">
  <h3>'Found '{{(friends | filter:searchText).length}} friends</h3>
  <div ng-switch="(friends | filter:searchText).length">
    <span class="ng-empty" ng-switch-when="0">No friends</span>
    <table ng-switch-default>
      <thead>  
        <tr>
          <th>Name</th>
          <th>Phone</th>
        </tr>
      </thead>
      <tbody>
      <tr ng-repeat="friend in friends | filter:searchText">
        <td>{{friend.name}}</td>
        <td>{{friend.phone}}</td>
      </tr>
    </tbody>
  </table>
</div>

1

Możesz użyć assłowa kluczowego, aby skierować kolekcję pod ng-repeatelement:

<table>
    <tr ng-repeat="task in tasks | filter:category | filter:query as res">
        <td>{{task.id}}</td>
        <td>{{task.description}}</td>
    </tr>
    <tr ng-if="res.length === 0">
        <td colspan="2">no results</td>
    </tr>
</table>

0

zwykle używam ng-show

<li ng-show="variable.length"></li>

gdzie zmienna jest zdefiniowana na przykład

<div class="list-group-item" ng-repeat="product in store.products">
   <li ng-show="product.length">show something</li>
</div>

0

możesz użyć ng-if, ponieważ nie jest to renderowane na stronie HTML i nie widzisz swojego znacznika HTML w inspekcji ...

<ul ng-repeat="item in items" ng-if="items.length > 0">
    <li>{{item}}<li>
</ul>
<div class="alert alert-info">there is no items!</div>
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.