使用ng-repeat和filter,如何判断哪些项是可见的?

时间:2022-08-23 23:49:20

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

我有一个数组,我用ng-repeat在我的角化应用中显示。我用过滤器和搜索输入的值过滤掉项目。它能够正常工作。但是,我有一个“选择所有”/“取消选择所有”选项,我只想选择列表中的visibile项目(满足当前搜索条件的项目)。

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?

如果不在我的控制器中执行相同的逻辑(例如,在我的每个对象上使用搜索值的索引),我如何知道哪些项当前被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?

由于这个问题不需要更多的细节,为了简单起见,我在这里对代码示例进行了显著的简化。有没有一种方法可以让我做我想做的事,或者我需要再做一次“搜索”吗?

3 个解决方案

#1


17  

You 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
  })
}

#2


1  

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.

您的问题是,ng-repeat是隔离的范围。因此,您无法从控制器/指令中引用由ng-repeat管理的内部列表。

As a result there are 2 options

因此有两个选择

  1. Bind the filtered list to ng-repeat from your controller/directive, so you maintain the filtered list.

    将过滤后的列表从控制器/指令绑定到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>
    
  2. 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
        }
    }
    

#3


1  

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.

如果你不想要过滤两次,你必须自己过滤数组,每次searchValue的改变和ng-repeat的过滤,在这种情况下,ng-change是有用的。

#1


17  

You 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
  })
}

#2


1  

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.

您的问题是,ng-repeat是隔离的范围。因此,您无法从控制器/指令中引用由ng-repeat管理的内部列表。

As a result there are 2 options

因此有两个选择

  1. Bind the filtered list to ng-repeat from your controller/directive, so you maintain the filtered list.

    将过滤后的列表从控制器/指令绑定到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>
    
  2. 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
        }
    }
    

#3


1  

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.

如果你不想要过滤两次,你必须自己过滤数组,每次searchValue的改变和ng-repeat的过滤,在这种情况下,ng-change是有用的。