AngularJS ng-повторити обробляти порожній список випадків


377

Я думав, що це буде дуже поширеною справою, але я не міг знайти, як з цим поводитися в AngularJS. Скажімо, у мене є список подій і хочу вивести їх за допомогою AngularJS, тоді це досить просто:

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

Але як я поводжусь із випадком, коли список порожній? Я хочу, щоб у полі, де знаходиться список, було щось із на зразок "Без подій" чи подібного. Єдине, що було б близько - це ng-switchз events.length(як я перевіряю, чи порожній, коли об’єкт, а не масив?), Але чи справді це єдиний варіант, який у мене є?


4
@ Артем відповідь хороша (+1). Ось групова дискусія в Google, яка використовує фільтр, для довідки / порівняння: groups.google.com/d/topic/angular/wR06cN5oVBQ/discussion
Марк Райкок

Відповіді:


569

Ви можете використовувати ngShow .

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

Див. Приклад .

Або ви можете використовувати ngHide

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

Див. Приклад .

Для об'єкта ви можете протестувати Object.keys .


1
Справді @ArtemAndreev. Коли "події" є порожнім масивом, він повертається істинним, навіть якщо масив порожній
Роб Юрлінк

Я думаю, що з Object.keys є проблема: jsfiddle.net/J9b5z , як би ви впоралися з цим?
Дані

5
nh-show працював у моєму випадку, але він не оновлює стан, коли я ставив фільтр і нічого не поверталося. Також об'єкт з'являється при першому завантаженні і зникає, коли процес повторення виконується при завантаженні сторінки.
dvdmn

1
@Дані спробуйте додати функцію до свого контролера, який виконує тест. Потім ви можете просто посилатися на директиву ng-hide="hasEvents()".
Містер S

Так дякую. Однак я сподівався, що буде більш елегантний спосіб без "забруднення" контролера.
Дані

370

І якщо ви хочете використовувати це з відфільтрованим списком, ось акуратний трюк:

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

3
Дуже корисний. Друкуйте, хоча з "відфільтрованими фрагментами".
равіші

1
Солодке! Вираз всередині ng-повтору виглядає дивно. Будь-який шанс ви могли це пояснити? Дякую!!
МК Сафі

7
@MKSafi, він створює нову змінну в області виклику filteredItemsі встановлює її значення (items | filter:keyword)- іншими словами, масив, повернутий фільтром
AlexFoxGill

17
ТАК! Ніндзя плюс очки! Це дозволяє економити кут від оцінювання складного фільтра двічі!
markmarijnissen

2
Також, мабуть, є деякі обмеження щодо цього у кількох фільтрах, як, "face in filteredFaces = faces|filter:{deleted: true} | orderBy:'text'але я згоден з усіма, це казковий трюк.
Fitter Man

29

Ви можете перевірити директиву angular-ui, ui-if якщо ви просто хочете видалити ulDOM, коли список порожній:

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

1
Дякую. Почуває себе чистішим, ніж просто приховувати це.
Prinzhorn

@Mortimer: значить, у цьому випадку нам потрібні кутові ui?
Шиббір Ахмед

ви можете використовувати ng-hideбез angular-ui, але він просто приховає вузол, він не видалить його з дерева DOM. Завдяки ui-ifдирективі angular-ui , він видалить вузол DOM. Отже, вам потрібно хоча б додати ui-ifдирективу з коду angular-ui до власного коду.
Мортімер

21
найновіший кутовий ng-ifвключений!
markmarijnissen

4
Зауважте, що ng-ifстворюється новий обсяг, де ng-hideйого немає. Це може спричинити несподівану поведінку.
Арнольд Даніельс

29

У новій версії angularjs правильною відповіддю на це питання є використання 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>

Це рішення не мерехтить, коли список збирається завантажити, оскільки список має бути визначений і довжиною 0, щоб повідомлення відображалося.

Ось планкер, щоб показати його у використанні: http://plnkr.co/edit/in7ha1wTlpuVgamiOblS?p=preview

Порада. Ви також можете показати текст, що завантажується, або спінер:

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

Це схоже на @Konrad 'ktoso' Малавського, але трохи простіше запам’ятати.

Перевірено з кутовим 1.4


3
Ви маєте на увазіng-if='!filteredItems.length'
абрунет

Як це зробити за допомогою декількох фільтрів?
Йордаш

@Jordash Просто продовжуйте їх розшифровувати item in items | filter: ... | filter: ...
Бернар

Приємне подальше уточнення<li ng-if="!filteredItems.length">
Matty J

Це чудово. Я раніше користувався набагато бруднішим способом, наприкладitem in (filteredItems = (items | filter: someFilter))
Firze

6

Ось інший підхід із використанням CSS замість JavaScript / AngularJS.

CSS:

.emptymsg {
  display: list-item;
}

li + .emptymsg {
  display: none;
}

Розмітка:

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

Якщо список порожній, <li ng-repe = "елемент у filteredItems"> тощо буде прокоментовано та стане коментарем замість елемента li.


Питання зазначає: "Я хочу, щоб у ньому був список повідомлень". Я також думаю, що невигідно розділяти логіку на таблиці стилів. Важко підтримувати і просити неприємностей.
Prinzhorn

1
@Prinzhorn, я думаю, що використання CSS є перевагою, оскільки логіка дуже проста і проста в обслуговуванні, CSS може використовуватись повторно для інших списків, і вона не покладається на JavaScript. Ніяких додаткових слухачів чи спостерігачів не потрібно. Повідомлення могло бути стильним, щоб воно було схоже на коробку, я просто не спростив відповідь.
Міріам Сальцер

Кілька місяців із запізненням, дано, але я згоден з Міріам, я вважаю, що ця відповідь геніальна.
Джон Комб

2

Ви можете використовувати цей 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

Ви можете використовувати asключове слово для позначення колекції під ng-repeatелементом:

<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

Я зазвичай використовую ng-show

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

де змінну ви визначаєте, наприклад

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

0

ви можете використовувати ng-if, тому що це не відображається на html-сторінці, і ви не бачите свій html-тег в огляді ...

<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>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.