Используя ng-repeat и filter, как определить, какие элементы видны?
У меня есть массив объектов, которые я показываю в своем приложении Angular, используя ng-repeat
. Я фильтрую элементы, используя filter
и значение ввода поиска. Он работает так, как ожидалось. Но у меня есть опция "выбрать все" / "отменить выбор", и я хочу только выбрать видимые элементы в списке (те, которые соответствуют текущим критериям поиска).
Не выполняя такую же логику в моем контроллере (т.е. используя indexOf
значение поиска для каждого из моих объектов), как я могу определить, какие элементы в настоящее время отфильтрованы ng-repeat
/filter
?
Мой взгляд:
<input type="text" ng-model="searchValue">
<input type="checkbox" ng-model="checkAll" ng-change="toggleAll()">
<tr ng-repeat="item in items | filter:searchValue">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
</tr>
Функция в моем контроллере:
$scope.toggleAll() {
for(var i in $scope.items){
// how can I tell if this item is filtered out in the view?
}
}
Я значительно упростил свои примеры кода здесь для простоты, так как этот вопрос не нуждается в более подробных деталях. Есть ли способ сделать то, что я думаю, или мне нужно снова выполнить "поиск"?
Ответы
Ответ 1
Вы можете привязать фильтрованный массив к другой переменной области видимости в вашем представлении, а затем получить доступ к этому в своем контроллере.
Вид:
<tr ng-repeat="item in filteredItems = (items | filter:searchValue)">
...
</tr>
Контроллер:
$scope.toggleAll = function () {
angular.forEach($scope.filteredItems, function (item) {
// do stuff
})
}
Ответ 2
Ваша проблема в том, что ng-repeat - выделенная область. В результате вы не можете ссылаться на внутренний список, который управляется ng-repeat из вашего контроллера/директивы.
В результате есть 2 варианта
-
Привяжите отфильтрованный список к ng-repeat из вашего контроллера/директивы, поэтому вы сохраняете отфильтрованный список.
//in your controller
$scope.filteredItems = $filter('yourFilter')($scope.items,$scope.searchText);
$scope.$watch('searchText', function(newValue){
$scope.filteredItems = $filter('yourFilter')($scope.items, newValue);
});
//in your view
<tr ng-repeat="item in filteredItems">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
</tr>
-
Выполните фильтр снова в своем контроллере/директиве
$scope.toggleAll() {
var items = $filter('yourFilter')($scope.items, $scope.searchText);
for(var i in items){
//set your selected property
}
}
Ответ 3
Фильтры Angular создают новый массив. Итак, чтобы выполнить действие с фильтрованными элементами, которые вам нужно будет захватить новый массив.
Что-то вроде:
$scope.toggleAll() {
var filteredItems = $filter('filter')($scope.items, $scope.searchValue);
for(var i in filteredItems) {
...
}
}
Если вы не хотите дважды фильтровать, вам придется каждый раз фильтровать массив каждый раз при изменении searchValue
и ng-repeat
по этому фильтруемому массиву ng-change полезен в этом случае.