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-switchevents.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: ... 一个不错的,进一步细化是&lt;li ng-if="!filteredItems.length"&gt; 这很棒。我之前一直在使用更脏的方法,比如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循环列表中序号怎么写

Angularjs列表项边距问题将ng-repeat元素与静态元素结合起来

使用 AngularJS 和 ng-repeat 初始化选择

AngularJS - 如何处理 ng-repeat 与预先存在的项目