AngularJS ng-repeat 处理空列表情况
Posted
技术标签:
【中文标题】AngularJS ng-repeat 处理空列表情况【英文标题】:AngularJS ng-repeat handle empty list case 【发布时间】:2012-09-02 15:14:52 【问题描述】:我认为这将是一件很常见的事情,但我找不到如何在 AngularJS 中处理它。假设我有一个事件列表并想用 AngularJS 输出它们,那么这很容易:
<ul>
<li ng-repeat="event in events">event.title</li>
</ul>
但是当列表为空时我该如何处理呢?我想在列表所在的位置放置一个消息框,其中包含“无事件”或类似内容。唯一可以接近的是ng-switch
和events.length
(当对象而不是数组时如何检查是否为空?),但这真的是我唯一的选择吗?
【问题讨论】:
@Artem 的回答很好 (+1)。这是一个使用过滤器的谷歌小组讨论,供参考/比较:groups.google.com/d/topic/angular/wR06cN5oVBQ/discussion 【参考方案1】:您可以使用ngShow。
<li ng-show="!events.length">No events</li>
见example。
或者你可以使用ngHide
<li ng-hide="events.length">No events</li>
见example。
对于对象你可以测试Object.keys。
【讨论】:
确实是@ArtemAndreev。当“events”为空数组时,即使数组为空,它也会返回true 我认为 Object.keys 有问题:jsfiddle.net/J9b5z,您将如何处理? nh-show 在我的情况下有效,但是当我放入过滤器并且没有返回任何内容时,它不会更新状态。此外,该对象在第一次加载时出现,并在页面加载完成重复过程时消失。 @Dani 尝试向您的控制器添加一个执行测试的函数。然后,您可以使用ng-hide="hasEvents()"
调用该指令。
好的,谢谢。不过,我希望有一种更优雅的方式,不会“污染”控制器。【参考方案2】:
如果您只想在列表为空时从 DOM 中删除 ul
,则可能需要查看 angular-ui directive ui-if
:
<ul ui-if="!!events.length">
<li ng-repeat="event in events">event.title</li>
</ul>
【讨论】:
谢谢。感觉比隐藏起来更干净。 @Mortimer:那么在这种情况下我们需要 angular-ui 吗? 你可以在没有 angular-ui 的情况下使用ng-hide
,但它只会隐藏节点,不会从 DOM 树中删除它。使用 angular-ui 的 ui-if
指令,它将删除 DOM 节点。因此,您至少需要将 angular-ui 代码中的 ui-if
指令添加到您自己的代码中。
最新 Angular 已包含 ng-if
!
请注意,ng-if
正在创建一个新范围,而 ng-hide
不是。这可能会导致意外行为。【参考方案3】:
如果您想将其与过滤列表一起使用,这是一个巧妙的技巧:
<ul>
<li ng-repeat="item in filteredItems = (items | filter:keyword)">
...
</li>
</ul>
<div ng-hide="filteredItems.length">No items found</div>
【讨论】:
非常有用。使用“filteredFragments”打错字。 甜蜜!不过,ng-repeat 中的表达式看起来很奇怪。你有机会解释一下吗?谢谢!! @MKSafi,它在名为filteredItems
的范围内创建一个新变量并将其值设置为 (items | filter:keyword)
- 换句话说,过滤器返回的数组
是的!忍者加分!这样可以避免 Angular 两次评估复杂的过滤器!
另外,使用多个过滤器似乎有一些限制,例如"face in filteredFaces = faces|filter:deleted: true | orderBy:'text'
,但我同意每个人的观点,这是一个绝妙的技巧。【参考方案4】:
对于较新版本的 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 才能显示消息。
这里有一个 plunker 来展示它的使用情况:http://plnkr.co/edit/in7ha1wTlpuVgamiOblS?p=preview
提示:您还可以显示加载文本或微调器:
<li ng-if="!list">( Loading... )</li>
【讨论】:
【参考方案5】:<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,但更容易记住。
使用 Angular 1.4 测试
【讨论】:
你的意思是ng-if='!filteredItems.length'
你如何使用多个过滤器做到这一点?
@Jordash 继续管他们item in items | filter: ... | filter: ...
一个不错的,进一步细化是<li ng-if="!filteredItems.length">
这很棒。我之前一直在使用更脏的方法,比如item in (filteredItems = (items | filter: someFilter))
【参考方案6】:
你可以使用这个 ng-switch:
<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>
【讨论】:
【参考方案7】:这是一种使用 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>
如果列表为空,
等会被注释掉,会变成comment而不是li元素。【讨论】:
问题说“我想在列表所在的位置有一个消息框”。我也认为将逻辑分离到 s 样式表中是不利的。难以维护和自找麻烦。 @Prinzhorn,我认为使用 CSS 是一个优势,因为逻辑非常简单且易于维护,CSS 可用于其他列表,并且不依赖于 JavaScript。不需要额外的听众或观察者。消息的样式可以看起来像一个盒子,我只是没有让答案保持简单。 晚了几个月,当然,但我同意 Miriam,我认为这个答案是天才。【参考方案8】:我通常使用 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>
【讨论】:
【参考方案9】:您可以使用 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>
【讨论】:
【参考方案10】:您可以使用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>
【讨论】:
以上是关于AngularJS ng-repeat 处理空列表情况的主要内容,如果未能解决你的问题,请参考以下文章
AngularJS:从模型数组拼接模型元素时,不会更新 ng-repeat 列表
如何使用ng-repeat使bxSlider在AngularJS中工作?
Angularjs列表项边距问题将ng-repeat元素与静态元素结合起来