Как показать элемент, только если вложенный ng-repeat не пуст?

StackOverflow https://stackoverflow.com//questions/20002481

  •  20-12-2019
  •  | 
  •  

Вопрос

У меня есть список списков, созданный с помощью вложенного ng-repeat.Каждый внешний ng-repeat содержит элемент div с меткой его внутреннего списка (например:«Группа А»).Сейчас я пытаюсь создать способ избежать показа этой метки, если внутренний список пуст из-за фильтрации (применяется с помощью входного текста поиска)

Вот плункер, объясняющий мою проблему и мою попытку решения: Планкр

Наличие «тяжелой» функции, такой как isGroupEmpty, кажется чрезвычайно громоздким. Есть ли способ сделать это гораздо проще?Я подумывал о перемещении метки внутри внутреннего ng-repeat и ng-show="$first" но это выглядит не очень хорошо

Это было полезно?

Решение

Я закончил со следующим решением, который отлично работал. 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>
.

Другие советы

ты мог бы использовать 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') в вашем контроллере, вызвав его с группой в качестве первого аргумента, filterFn в качестве второго и сохраните результат в своей области.

Я использовал следующее:

<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>
.

Проверка, имеет ли массив длиной 0, не является дорогой операцией.Если вы хотите показать только список, имеющие элемент, поместите фильтр на внешнем массиве, который принимает массив массивов и возвращает только массивы, которые имеют длину, отличную от 0.

Вы также можете скрыть внутренний div, если массив== false.

http://plnkr.co/edit/gist:3510140

http://plnkr.co/edit/gr5upnrdbrfuyq0ilhmg?p=preview / P >.

Ваш Plunkr был довольно сложен и трудно сорнять, поэтому я снова создал то, что вы хотели использовать скрипку.Общая идея моего подхода - это отфильтровывать предметы из массива, а не подразделение.И делать только отфильтрованные элементы, когда текстовые изменения изменяются.Итак, вот разметка:

<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();
}
.

widdle : http://jsfiddle.net/2hrws/ P >.

Причина, по которой я создаю новый массив, а не использовать фактический фильтр для удаления результатов, заключается в том, что угловые не любят создавать динамические массивы на летуще в фильтрах.Это потому, что он не назначает $$ Hashkey, и все просто не выключаются правильно, когда грязная проверка.Я получил представление о том, как делать то, что вам нужно из этой темы по этому вопросу:

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top