Подтвердить что ты не робот

Используя 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?
     }
}

Я значительно упростил свои примеры кода здесь для простоты, так как этот вопрос не нуждается в более подробных деталях. Есть ли способ сделать то, что я думаю, или мне нужно снова выполнить "поиск"?

4b9b3361

Ответ 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 полезен в этом случае.