【问题标题】:AngularJS ng-repeat handle empty list caseAngularJS ng-repeat 处理空列表情况
【发布时间】:2024-04-12 10:40:01
【问题描述】:

我认为这将是一件很常见的事情,但我找不到如何在 AngularJS 中处理它。假设我有一个事件列表并想用 AngularJS 输出它们,那么这很容易:

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

但是当列表为空时我该如何处理呢?我想在列表所在的位置放置一个消息框,其中包含“无事件”或类似内容。唯一可以接近的是ng-switchevents.length(当对象而不是数组时如何检查是否为空?),但这真的是我唯一的选择吗?

【问题讨论】:

标签: javascript angularjs angularjs-ng-repeat angularjs-ng-show


【解决方案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>
          

          【讨论】: