AngularJS - скрыть родительский элемент, если дочерний цикл пуст (отфильтрован) - программирование
Подтвердить что ты не робот

AngularJS - скрыть родительский элемент, если дочерний цикл пуст (отфильтрован)

У меня есть случай, когда у меня есть вложенные циклы, в которых дочерний один создается функцией фильтра, которая принимает родительский аргумент. У меня также есть еще один фильтр, который просто сравнивает текст. Вот пример

<div ng-repeat="group in groups">
  {{group.name}}
  <div ng-repeat="material in materials | filter:filterByGroup(group) | filter:search ">
    {{material.name}}
  </div>
</div>

Теперь моя проблема в том, что когда применяется filter:search и отфильтровывает все результаты в определенной группе, я хотел бы скрыть группу (и не оставлять пустую group.name висящую без дочерних элементов).

У меня нет материалов в группе, поэтому я не располагаю этой информацией в родительской области ng-repeat. Вопрос в том, есть ли способ получить доступ к вложенному ng-repeat и увидеть его счетчик из родительского элемента и скрыть родителя, если это число равно 0.

UPDATE

Вот скрипка, которая лучше объясняет ситуацию: fiddle

Основная проблема заключается в том, что я не хочу связывать свои материалы с группами. Я мог бы сделать это, если ничего не работает, но это звучит как перегрузка (так как тогда мне нужно будет в основном фильтровать результаты дважды), если бы я мог сделать это, просто проверив вложенный цикл.

Спасибо

4b9b3361

Ответ 1

Было предложено гораздо более чистое решение ЗДЕСЬ.

Что вам нужно сделать, это обернуть соответствующую область с помощью ng-show/ng-if на основе выражения, которое применяет фильтр к структуре данных и извлекает длину. Вот как это работает в вашем примере:

  <div ng-show="(materials | filter:filterByGroup(group)).length">
    <div ng-repeat="group in groups">
      {{group.name}}
      <div ng-repeat="material in materials | filter:filterByGroup(group) | filter:search ">
        {{material.name}}
      </div>
    </div>
  </div>

Это позволяет скрыть сложные структуры, когда они пусты, из-за фильтрации, например. таблицу результатов.

Ответ 2

Я видел этот прецедент несколько раз, здесь мое решение:

<div ng-repeat="group in groups">
    <div ng-repeat="material in materials | filter:filterByGroup(group) | filter:search ">
        <span ng-show="$first">
            {{group.name}}<br/>
        </span>
        {{material.name}}
    </div>
</div>

Вы можете использовать $first или $last в пределах области ng-repeat, чтобы показывать только первую и последнюю из каждой группы. если вначале нет $, он не будет отображать имя группы.

Я только что реализовал это в своем блоге и обновил вашу скрипку здесь: http://jsfiddle.net/ke793/1/

Я не уверен, что это самое элегантное решение, но оно кажется довольно простым и работает. Мне бы хотелось увидеть, как другие решили это.

Обновление: только что вы поняли, что можете использовать ng-if, чтобы не допустить, чтобы имя группы ударялось по dom за пределами элемента $first. Немного чище, чем ng-hide/ng-show, который каждый раз устанавливает display: none в дополнительный заголовок.

Ответ 3

Если вы можете запросить материалы по группам, и вы ожидаете сделать это для каждой группы, почему бы не сделать это сразу, когда вы инициализируете представление и создаете модель с группами, имеющими материалы? Если вы можете это сделать, вы можете использовать ng-show, чтобы скрыть группы, в которых есть материалы.

Вам, кажется, нужно знать, что у группы есть материалы или нет? Здесь сценарий, не зная много фона:

<div ng-controller="MyCtrl">

  <div ng-repeat="group in groups">
      <div ng-show="groupHasMaterials(group)">{{group.name}}</div>
      <div ng-repeat="material in materialsByGroup(group)">
          <div>{{material.name}}</div>
      </div>
  </div>

</div>


<script>
var myApp = angular.module('myApp',[]);

function MyCtrl($scope) {

    var groups = [
        {'name':'group one'},
        {'name':'group two'}
    ];

    var materials = [
        {'name':'material1'},
        {'name':'material2'},
        {'name':'material3'}
    ];

    $scope.groups = groups;
    $scope.materials = materials;

    $scope.groupHasMaterials = function(group){
        return $scope.materialsByGroup(group).length > 0;    
    }

    $scope.materialsByGroup = function(group){
        return group.name === 'group one' 
            ? [materials[0], materials[1]] 
            : [];
    }
}
</script>

скрипка с группами