AngularJS ng-repeat จัดการรายการที่ว่างเปล่า


377

ฉันคิดว่านี่จะเป็นสิ่งที่ธรรมดามาก แต่ฉันไม่สามารถหาวิธีจัดการกับมันได้ใน AngularJS สมมติว่าฉันมีรายการกิจกรรมและต้องการส่งออกด้วย AngularJS แล้วมันค่อนข้างง่าย:

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

แต่ฉันจะจัดการกรณีได้อย่างไรเมื่อรายการว่างเปล่า? ฉันต้องการให้กล่องข้อความอยู่ในตำแหน่งที่รายการอยู่กับบางสิ่งเช่น "ไม่มีเหตุการณ์" หรือคล้ายกัน สิ่งเดียวที่จะเข้ามาใกล้คือng-switchด้วยevents.length(ฉันจะตรวจสอบว่าว่างเปล่าเมื่อวัตถุและไม่ใช่อาร์เรย์ได้อย่างไร) แต่นั่นเป็นตัวเลือกเดียวที่ฉันมีจริงหรือ


4
@ คำตอบของ Artem นั้นดี (+1) นี่คือการสนทนากลุ่ม google ที่ใช้ตัวกรองสำหรับการอ้างอิง / การเปรียบเทียบ: groups.google.com/d/topic/angular/wR06cN5oVBQ/discussion
Mark Rajcok

คำตอบ:


569

คุณสามารถใช้ngShow

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

ดูตัวอย่าง

หรือคุณสามารถใช้ngHide

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

ดูตัวอย่าง

สำหรับวัตถุที่คุณสามารถทดสอบObject.keys


1
แน่นอน @ArtemAndreev เมื่อ "events" เป็นอาร์เรย์ว่างเปล่ามันจะส่งกลับค่าจริงแม้ว่าอาร์เรย์จะว่างเปล่า
Rob Juurlink

ฉันคิดว่ามีปัญหากับ Object.keys: jsfiddle.net/J9b5zคุณจะจัดการกับสิ่งนี้อย่างไร
Dani

5
nh-show ทำงาน id กรณีของฉัน แต่ไม่ได้อัพเดตสถานะเมื่อฉันใส่ตัวกรองเข้าไปและไม่มีอะไรคืนมา นอกจากนี้วัตถุที่ปรากฏในการโหลดครั้งแรกและหายไปเมื่อกระบวนการทำซ้ำในการโหลดหน้า
dvdmn

1
@Dani ลองเพิ่มฟังก์ชั่นให้กับคอนโทรลเลอร์ของคุณเพื่อทำการทดสอบ ng-hide="hasEvents()"จากนั้นคุณสามารถเพียงแค่เรียกใช้คำสั่งกับ
นาย S

ใช่ขอบคุณ. อย่างไรก็ตามฉันหวังว่าจะมีวิธีที่สวยงามกว่าโดยไม่ "ควบคุมมลพิษ" ตัวควบคุม
Dani

370

และหากคุณต้องการใช้สิ่งนี้กับรายการที่กรองแล้วนี่เป็นเคล็ดลับที่เรียบร้อย:

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

3
มีประโยชน์มาก. สะกดผิดด้วย "filteredFragments"
ravishi

1
หวาน! การแสดงออกภายใน ng-repeat นั้นดูแปลก ๆ โอกาสใดที่คุณสามารถอธิบายได้ ขอบคุณ !!
MK Safi

7
@MKSafi มันกำลังสร้างตัวแปรใหม่บนขอบเขตที่เรียกfilteredItemsและตั้งค่าเป็น(items | filter:keyword)- กล่าวอีกอย่างคืออาร์เรย์ที่ส่งคืนโดยตัวกรอง
AlexFoxGill

17
ใช่! คะแนนนินจาบวก! สิ่งนี้ช่วยประหยัดเชิงมุมจากการประเมินตัวกรองที่ซับซ้อนสองครั้ง!
markmarijnissen

2
นอกจากนี้ยังมีข้อ จำกัด บางอย่างเกี่ยวกับเรื่องนี้ด้วยตัวกรองหลายตัวเช่น"face in filteredFaces = faces|filter:{deleted: true} | orderBy:'text'แต่ฉันเห็นด้วยกับทุกคนนี่เป็นเคล็ดลับที่เหลือเชื่อ
ผู้ชายช่างฟิต

29

คุณอาจต้องการดูคำสั่ง angular-ui ui-ifหากคุณต้องการลบออกulจาก DOM เมื่อรายการว่างเปล่า:

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

1
ขอบคุณ รู้สึกสะอาดกว่าแค่ซ่อนมันไว้
Prinzhorn

@Mortimer: ดังนั้นในกรณีนี้เราต้องการ angular-ui หรือไม่
Shibbir Ahmed

คุณสามารถใช้ng-hideโดยไม่มี angular-ui แต่มันจะซ่อนโหนดมันจะไม่ลบมันออกจากทรี DOM ด้วยui-ifคำสั่งของ angular-ui มันจะลบโหนด DOM ดังนั้นอย่างน้อยคุณต้องเพิ่มui-ifคำสั่งจากโค้ด angular-ui ให้กับรหัสของคุณเอง
Mortimer

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' Malawski แต่จดจำได้ง่ายกว่าเล็กน้อย

ทดสอบกับเชิงมุม 1.4


3
คุณหมายถึงng-if='!filteredItems.length'
abrunet

คุณจะทำอย่างไรกับตัวกรองหลายตัว?
Jordash

@ 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-repeat = "รายการใน filteredItems"> ฯลฯ จะได้รับการใส่ความคิดเห็นและจะกลายเป็นความคิดเห็นแทนองค์ประกอบ li


คำถามบอกว่า "ฉันต้องการให้กล่องข้อความอยู่ในตำแหน่งที่รายการอยู่" ฉันคิดว่ามันก็เป็นข้อเสียเปรียบในการแยกตรรกะออกเป็นสไตล์ชีท บำรุงรักษายากและถามหาปัญหา
Prinzhorn

1
@Prinzhorn ฉันคิดว่าการใช้ CSS เป็นข้อได้เปรียบเพราะตรรกะนั้นง่ายมากและง่ายต่อการดูแลรักษา CSS นั้นสามารถนำกลับมาใช้ใหม่ได้สำหรับรายการอื่น ๆ และไม่ต้องใช้ JavaScript ไม่จำเป็นต้องมีผู้ฟังหรือผู้ดูเพิ่มเติม ข้อความอาจมีสไตล์เหมือนกล่องฉันแค่ไม่ตอบคำถามง่ายๆ
Miriam Salzer

ปลายไม่กี่เดือนได้รับ แต่ฉันเห็นด้วยกับ Miriam ฉันคิดว่าคำตอบนี้เป็นอัจฉริยะ
Jon Combe

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>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.