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
Основная проблема заключается в том, что я не хочу связывать свои материалы с группами. Я мог бы сделать это, если ничего не работает, но это звучит как перегрузка (так как тогда мне нужно будет в основном фильтровать результаты дважды), если бы я мог сделать это, просто проверив вложенный цикл.
Спасибо
Ответы
Ответ 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>
скрипка с группами