AngularJS ng-repeat xử lý trường hợp danh sách trống


377

Tôi nghĩ rằng đây sẽ là một điều rất phổ biến, nhưng tôi không thể tìm ra cách xử lý nó trong AngularJS. Giả sử tôi có một danh sách các sự kiện và muốn xuất chúng bằng AngularJS, thì điều đó khá dễ dàng:

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

Nhưng làm thế nào để tôi xử lý trường hợp khi danh sách trống? Tôi muốn có một hộp thông báo ở vị trí có danh sách với nội dung như "Không có sự kiện" hoặc tương tự. Điều duy nhất sẽ đến gần là ng-switchvới events.length(làm cách nào để kiểm tra nếu trống khi một đối tượng và không phải là một mảng?), Nhưng đó có thực sự là lựa chọn duy nhất tôi có không?


4
@ Câu trả lời của Artem là tốt (+1). Đây là một cuộc thảo luận nhóm google sử dụng bộ lọc, để tham khảo / so sánh: Groups.google.com/d/topic/angular/wR06cN5oVBQ/discussion
Mark Rajcok

Câu trả lời:


569

Bạn có thể sử dụng ngShow .

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

Xem ví dụ .

Hoặc bạn có thể sử dụng ngHide

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

Xem ví dụ .

Đối với đối tượng bạn có thể kiểm tra Object.keys .


1
Thật vậy @ArtemAndreev. Khi "sự kiện" là một mảng trống, nó sẽ trả về đúng mặc dù mảng đó trống
Rob Juurlink

Tôi nghĩ có vấn đề với Object.keys: jsfiddle.net/J9b5z , bạn sẽ xử lý vấn đề này như thế nào?
Dani

5
nh-show làm việc id trường hợp của tôi nhưng nó không cập nhật trạng thái khi tôi đặt bộ lọc vào và không có gì trả lại. Ngoài ra, đối tượng xuất hiện trong lần tải đầu tiên và biến mất khi quá trình lặp lại được thực hiện khi tải trang.
dvdmn

1
@Dani thử thêm một chức năng vào bộ điều khiển của bạn để thực hiện kiểm tra. Sau đó bạn có thể chỉ cần gọi lệnh với ng-hide="hasEvents()".
Ông S

Vâng cảm ơn. Tuy nhiên, tôi hy vọng sẽ có một cách thanh lịch hơn mà không làm "ô nhiễm" bộ điều khiển.
Dani

370

Và nếu bạn muốn sử dụng điều này với một danh sách được lọc thì đây là một mẹo nhỏ:

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

3
Rất hữu ích. Typo mặc dù với "lọc được lọc".
ravishi

1
Ngọt! Các biểu hiện bên trong ng-repeat trông lạ. Bất kỳ cơ hội bạn có thể giải thích nó? Cảm ơn!!
MK Safi

7
@MKSafi, nó đang tạo một biến mới trên phạm vi được gọi filteredItemsvà đặt giá trị của nó thành (items | filter:keyword)- nói cách khác, mảng được bộ lọc trả về
AlexFoxGill

17
ĐÚNG! Ninja cộng điểm! Điều này tiết kiệm góc từ đánh giá một bộ lọc phức tạp hai lần!
markmarijnissen

2
Ngoài ra, dường như có một số hạn chế xung quanh vấn đề này với nhiều bộ lọc, "face in filteredFaces = faces|filter:{deleted: true} | orderBy:'text'nhưng tôi đồng ý với tất cả mọi người, đây là một mẹo tuyệt vời.
Fitter Man

29

Bạn có thể muốn kiểm tra lệnh angular-ui ui-if nếu bạn chỉ muốn xóa ulkhỏi DOM khi danh sách trống:

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

1
Cảm ơn. Cảm thấy sạch sẽ hơn là chỉ che giấu nó.
Prinzhorn

@Mortimer: vậy trong trường hợp này chúng ta có cần angular-ui không?
Shibbir Ahmed

bạn có thể sử dụng ng-hidemà không cần angular-ui, nhưng nó sẽ chỉ ẩn nút, nó sẽ không xóa nó khỏi cây DOM. Với ui-ifchỉ thị của angular-ui , nó sẽ loại bỏ nút DOM. Vì vậy, ít nhất bạn cần thêm lệnh ui-iftừ mã angular-ui vào mã của riêng bạn.
Mortimer

21
góc cạnh mới nhất đã ng-ifbao gồm!
markmarijnissen

4
Lưu ý rằng ng-ifđang tạo một phạm vi mới, trong đó ng-hidekhông. Điều này có thể gây ra hành vi bất ngờ.
Arnold Daniels

29

Với các phiên bản mới hơn của angularjs, câu trả lời chính xác cho câu hỏi này là sử dụng 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>

Giải pháp này sẽ không nhấp nháy khi danh sách sắp tải xuống vì danh sách phải được xác định và có độ dài bằng 0 để thông báo hiển thị.

Đây là một plunker để hiển thị nó được sử dụng: http://plnkr.co/edit/in7ha1wTlpuVgamiOblS?p=preview

Mẹo: Bạn cũng có thể hiển thị văn bản đang tải hoặc spinner:

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

Điều này tương tự với @Konrad 'ktoso' Malawski nhưng dễ nhớ hơn một chút.

Đã thử nghiệm với Angular 1.4


3
Ý bạn làng-if='!filteredItems.length'
bỏ qua

Làm thế nào để bạn làm điều này với nhiều bộ lọc?
Jordash

@Jordash Chỉ cần giữ đường ống cho họ item in items | filter: ... | filter: ...
Bernard

Một sự tinh tế, tốt đẹp hơn nữa là<li ng-if="!filteredItems.length">
Matty J

Điều đó thật tuyệt. Tôi đã sử dụng một phương pháp bẩn hơn trước đây như thếitem in (filteredItems = (items | filter: someFilter))
Firze

6

Đây là một cách tiếp cận khác bằng CSS thay vì JavaScript / AngularJS.

CSS:

.emptymsg {
  display: list-item;
}

li + .emptymsg {
  display: none;
}

Đánh dấu:

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

Nếu danh sách trống, <li ng-repeat = "mục trong bộ lọc được lọc">, v.v. sẽ được nhận xét và sẽ trở thành nhận xét thay vì phần tử li.


Câu hỏi cho biết "Tôi muốn có một hộp thông báo ở vị trí có danh sách". Tôi cũng nghĩ rằng thật bất lợi khi tách logic thành biểu định kiểu. Khó để duy trì và yêu cầu rắc rối.
Prinzhorn

1
@Prinzhorn, tôi nghĩ rằng sử dụng CSS là một lợi thế vì logic rất đơn giản và dễ bảo trì, CSS có thể sử dụng lại cho các danh sách khác và nó không phụ thuộc vào JavaScript. Không có người nghe hoặc người theo dõi bổ sung là cần thiết. Thông điệp có thể được tạo kiểu trông giống như một cái hộp, tôi chỉ không giữ câu trả lời đơn giản.
Miriam Salzer

Một vài tháng muộn, được cấp, nhưng tôi đồng ý với Miriam, tôi nghĩ câu trả lời này là thiên tài.
Jon Combe

2

Bạn có thể sử dụng ng-switch này:

<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

Bạn có thể sử dụng astừ khóa để giới thiệu bộ sưu tập theo một ng-repeatyếu tố:

<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

tôi thường sử dụng ng-show

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

ví dụ về biến bạn xác định

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

0

bạn có thể sử dụng ng-if vì đây không phải là kết xuất trong trang html và bạn không thấy thẻ html của mình khi kiểm tra ...

<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>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.