I have an array of objects that I'm displaying in my Angular app using ng-repeat
. I'm filtering out items using filter
and the value of a search input. It works as expected. But, I have a "select all" / "deselect all" option and I only want to select the visibile items in the list (the ones that meet the current search criteria).
Without performing the same logic in my controller (i.e. using indexOf
the search value on each of my objects), how can I tell which items are currently filtered out by ng-repeat
/filter
?
My view:
<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>
A function in my controller:
$scope.toggleAll() {
for(var i in $scope.items){
// how can I tell if this item is filtered out in the view?
}
}
I have significantly simplified my code samples here for simplicity since this question doesn't need much more detail. Is there a way to do what I'm thinking or do I need to perform the "search" again?
I have an array of objects that I'm displaying in my Angular app using ng-repeat
. I'm filtering out items using filter
and the value of a search input. It works as expected. But, I have a "select all" / "deselect all" option and I only want to select the visibile items in the list (the ones that meet the current search criteria).
Without performing the same logic in my controller (i.e. using indexOf
the search value on each of my objects), how can I tell which items are currently filtered out by ng-repeat
/filter
?
My view:
<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>
A function in my controller:
$scope.toggleAll() {
for(var i in $scope.items){
// how can I tell if this item is filtered out in the view?
}
}
I have significantly simplified my code samples here for simplicity since this question doesn't need much more detail. Is there a way to do what I'm thinking or do I need to perform the "search" again?
Share Improve this question asked Jun 8, 2015 at 20:17 amlyhammamlyhamm 1,1502 gold badges20 silver badges37 bronze badges 2- Check out @azium 's comment on my answer. You'll probably want to use angular.forEach – allienx Commented Jun 8, 2015 at 20:40
- Of course, I was just throwing it out there as a quick example! Thanks. – amlyhamm Commented Jun 9, 2015 at 12:37
3 Answers
Reset to default 20You can bind the filtered array to another scope variable in your view, then access that in your controller.
View:
<tr ng-repeat="item in filteredItems = (items | filter:searchValue)">
...
</tr>
Controller:
$scope.toggleAll = function () {
angular.forEach($scope.filteredItems, function (item) {
// do stuff
})
}
Your issue is that ng-repeat is scope isolated. As a result you can't refer to the internal list that is being managed by ng-repeat from your controller/directive.
As a result there are 2 options
Bind the filtered list to ng-repeat from your controller/directive, so you maintain the filtered list.
//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>
Perform the filter again in your controller/directive
$scope.toggleAll() { var items = $filter('yourFilter')($scope.items, $scope.searchText); for(var i in items){ //set your selected property } }
Angular filters create a new array. So in order to perform an action on the filtered items you're going to have to capture the new array.
Something like:
$scope.toggleAll() {
var filteredItems = $filter('filter')($scope.items, $scope.searchValue);
for(var i in filteredItems) {
...
}
}
If you don't want to filter twice you'll have to filter the array yourself every time searchValue
changes and ng-repeat
over that filtered array, ng-change is useful in that case.