如果嵌套的ng-repeat不为空,我该如何只显示一个元素?

时间:2013-11-15 13:44:29

标签: angularjs angularjs-ng-repeat

我有一个列表列表,使用嵌套的ng-repeat创建。每个外部ng-repeat包含一个带有内部列表标签的div(例如:“A组”)。我现在正试图创建一种避免显示此标签的方法,如果内部列表由于过滤而为空(由输入搜索文本应用)

以下是一名解说我的问题和尝试解决方案的人:Plnkr

拥有像isGroupEmpty这样的'重'功能似乎非常麻烦 - 有没有办法以更简单的方式做到这一点?我想要在内部ng-repeat中移动标签并使用ng-show="$first",但它看起来不太好

6 个答案:

答案 0 :(得分:60)

我最终得到了以下完美解决方案。 Plnkr

通过在内部ng-repeat中设置变量,我能够根据这个变量长度评估ng-show,如下所示:

<input ng-model='searchText'/>
<span ng-show='filtered.length > 0'>
  <ul>
    <li ng-repeat='el in filtered = (model | filter:searchText)'>
      <div>{{el.label}}</div>
    </li>
  </ul>
</span>

答案 1 :(得分:10)

你可以利用ng-init,这样你只会调用过滤器一次:

<div ng-repeat='(key,group) in model'>
  <div ng-init="filtered = (group | filter:filterFn)"></div>
  <div ng-show="filtered.length !== 0">
    <div>{{key}}</div>
    <ul>
      <li ng-repeat="el in filtered">
        <div>{{el.label}}</div>
      </li>
    </ul>
  </div>
 </div>

通常情况下使用ng-init并不是一个好习惯,但我想它解决了两次调用过滤器的问题。 另一种方法是通过javascript使用过滤器 - 您可以在控制器中注入$ filter并检索'filter'$filter('filter'),将group作为其第一个参数调用它,filterFn作为其第二个参数,并将其结果存储在您的范围。

答案 2 :(得分:3)

我使用了以下内容:

<ul>
    <li ng-repeat="menuItem in menuItems"><a href="Javascript:void(0);"><span class="fa {{menuItem.icon}} fa-lg"></span>{{menuItem.itemName}}</a>
    <span ng-show='menuItem.subItems.length > 0'>
        <ul>
            <li ng-repeat="subItem in menuItem.subItems"><a href="Javascript:void(0);">{{subItem.itemName}}</a></li>
        </ul>
    </span>
</li>

答案 3 :(得分:1)

检查数组的长度是否为0并不是一项昂贵的操作。如果您只想显示包含item的列表,请在外部数组上放置一个带有数组数组的过滤器,并仅返回长度不等于0的数组。

如果数组== false,你也可以隐藏内部div。

<击> http://plnkr.co/edit/gist:3510140

http://plnkr.co/edit/Gr5uPnRDbRfUYq0ILhmG?p=preview

答案 4 :(得分:0)

你的傻瓜很复杂,很难清除,所以我用小提琴重新创造了你想要的东西。我的方法背后的一般想法是过滤掉数组中的项,而不是子数组。并且仅在文本更改时执行过滤后的项目。所以这是标记:

<div ng-app="app">
    <div ng-controller="ParentCtrl">
        <input data-ng-model="filterText" data-ng-change="updateTypes()" />
        <div data-ng-repeat="type in filteredTypes">
            {{ type.name }}
            <ul>
                <li style="margin-left:20px;" data-ng-repeat="entry in type.entries">
                    - {{ entry.name }}
                </li>
            </ul>
        </div>
    </div>
</div>

这是代码:

angular.module('app', [])

function ParentCtrl($scope){
    $scope.filterText = "";
    $scope.types = [
        { name: "type1", entries: [{ name: "name1"}, { name: "name2"}, { name: "name3"}]},
        { name: "type2", entries: [{ name: "name1"}, { name: "name3"}, { name: "name3"}]},
        { name: "type3", entries: [{ name: "name1"}, { name: "name2"}, { name: "name5"}]},
            { name: "type4", entries: [{ name: "name4"}, { name: "name2"}, { name: "name3"}]}
    ];

    $scope.filteredTypes = [];
    $scope.updateTypes = function(){
        $scope.filteredTypes.length = 0;
        for(var x = 0; x < $scope.types.length; x++){
            if($scope.filterText === ""){
                $scope.filteredTypes.push($scope.types[x]);    
            }
            else{
                var entries = [];
                for(var y = 0; y < $scope.types[x].entries.length; y++){
                    if($scope.types[x].entries[y].name.indexOf($scope.filterText) !== -1){
                       entries.push($scope.types[x].entries[y]);   
                    }                        
                }
                if(entries.length > 0){
                    $scope.filteredTypes.push({
                        name: $scope.types[x].name,
                        entries: entries
                    });
                }
            }
        }
    }
    $scope.updateTypes();
}

小提琴http://jsfiddle.net/2hRws/

我正在创建一个新数组并且不使用实际过滤器来移除结果的原因是angular不喜欢在过滤器中动态创建动态数组。这是因为它没有分配$$ hashKey,而且在脏检查时它们没有正确排列。我想到了如何在这个问题上做了你需要的事情:https://groups.google.com/forum/#!topic/angular/IEIQok-YkpU

答案 5 :(得分:0)

我只是略微修改了您的list-widget.html,看到它的实际效果: plunkr

这个想法很简单 - 对ng-show使用相同的过滤器:

<div ng-show="group | filter:searchText">{{ key }}</div>

只有存在未经过滤的商品时,标签才会显示。

在我的示例中,我使用searchText进行过滤,因为我不熟悉CoffeeScript。