Как отобразить длину отфильтрованных данных ng-repeat

У меня есть массив данных, который содержит много объектов (формат JSON). В качестве содержимого этого массива можно принять следующее:

var data = [
  {
    "name": "Jim",
    "age" : 25
  },
  {
    "name": "Jerry",
    "age": 27
  }
];

Теперь я показываю эти данные как:

<div ng-repeat="person in data | filter: query">
</div

Здесь запрос моделируется в поле ввода, в котором пользователь может ограничить отображаемые данные.

Теперь у меня есть другое место, в котором я показываю текущее количество отображаемых людей/людей, т.е. Showing {{data.length}} Persons

Что я хочу сделать, так это то, что когда пользователь ищет человека, а отображаемые данные отфильтровываются на основе запроса, Showing...persons также изменяет значение отображаемых в настоящее время людей. Но этого не происходит. Он всегда отображает полных лиц в данных, а не отфильтрованных - как я могу получить количество отфильтрованных данных?

Ответ 1

Для Angular 1,3 + (кредиты @Tom)

Используйте выражение псевдонима (Docs: Angular 1.3.0: ngRepeat, прокрутите вниз до раздела "Аргументы" ):

<div ng-repeat="person in data | filter:query as filtered">
</div>

Для Angular до 1.3

Назначьте результаты новой переменной (например, filtered) и получите доступ к ней:

<div ng-repeat="person in filtered = (data | filter: query)">
</div>

Отобразить количество результатов:

Showing {{filtered.length}} Persons

Попробуйте аналогичный пример. Кредиты идут на Павел Козловский

Ответ 2

Для полноты, в дополнение к предыдущим ответам (выполнить расчет видимых людей внутри контроллера), вы также можете выполнить эти вычисления в своем HTML-шаблоне, как показано в примере ниже.

Предполагая, что ваш список людей находится в переменной data, и вы фильтруете людей с помощью модели query, следующий код будет работать для вас:

<p>Number of visible people: {{(data|filter:query).length}}</p>
<p>Total number of people: {{data.length}}</p>
  • {{data.length}} - печатает общее количество людей
  • {{(data|filter:query).length}} - печатает отфильтрованное количество людей

Примечание, что это решение отлично работает, если вы хотите использовать отфильтрованные данные только один раз на странице. Однако, если вы используете отфильтрованные данные более одного раза, например. для представления элементов и отображения длины отфильтрованного списка я бы предложил использовать выражение alias (описано ниже) для AngularJS 1.3 + или решение, предложенное @Wumms для версии AngularJS ранее до 1.3.

Новая функция в Angular 1.3

Создатели AngularJS также заметили эту проблему и в версии 1.3 (beta 17) добавили выражение "псевдоним", которое будет хранить промежуточные результаты ретранслятора после того, как фильтры были применены, например
<div ng-repeat="person in data | filter:query as results">
    <!-- template ... -->
</div>

<p>Number of visible people: {{results.length}}</p>

выражение псевдонима предотвратит проблему с несколькими фильтрами.

Я надеюсь, что это поможет.

Ответ 3

ngRepeat создает копию массива при применении фильтра, поэтому вы не можете использовать исходный массив для ссылки только на отфильтрованные элементы.

В вашем случае лучше всего применить фильтр внутри вашего контроллера, используя службу $filter:

function MainCtrl( $scope, filterFilter ) {
  // ...

  $scope.filteredData = myNormalData;

  $scope.$watch( 'myInputModel', function ( val ) {
    $scope.filteredData = filterFilter( myNormalData, val );
  });

  // ...
}

И затем вместо этого вы используете свойство filteredData в своем представлении. Вот рабочий Plunker: http://plnkr.co/edit/7c1l24rPkuKPOS5o2qtx?p=preview

Ответ 4

Так как AngularJS 1.3 вы можете использовать псевдонимы:

item in items | filter:x as results

и где-нибудь:

<span>Total {{results.length}} result(s).</span>

От docs:

Вы также можете предоставить необязательное выражение псевдонима, которое затем будет хранить промежуточный результаты повторителя после применения фильтров. типично это используется для отображения специального сообщения, когда фильтр активен ретранслятор, но отфильтрованный набор результатов пуст.

Например: элемент в элементах | фильтр: x, поскольку результаты сохранят фрагмент повторяющихся элементов в качестве результатов, но только после элементов были обработаны через фильтр.

Ответ 5

Также полезно отметить, что вы можете хранить несколько уровней результатов, группируя фильтры

all items: {{items.length}}
filtered items: {{filteredItems.length}}
limited and filtered items: {{limitedAndFilteredItems.length}}
<div ng-repeat="item in limitedAndFilteredItems = (filteredItems = (items | filter:search) | limitTo:25)">...</div>

здесь демонстрационная скрипка

Ответ 6

Самый простой способ, если у вас

<div ng-repeat="person in data | filter: query"></div>

Отфильтрованная длина данных

<div>{{ (data | filter: query).length }}</div>

Ответ 7

Здесь приведен пример См. в Plunker

  <body ng-controller="MainCtrl">
    <input ng-model="search" type="text">
    <br>
    Showing {{data.length}} Persons; <br>
    Filtered {{counted}}
    <ul>
      <li ng-repeat="person in data | filter:search">
        {{person.name}}
      </li>
    </ul>
  </body>

<script> 
var app = angular.module('angularjs-starter', [])

app.controller('MainCtrl', function($scope, $filter) {
  $scope.data = [
    {
      "name": "Jim", "age" : 21
    }, {
      "name": "Jerry", "age": 26
    }, {
      "name": "Alex",  "age" : 25
    }, {
      "name": "Max", "age": 22
    }
  ];

  $scope.counted = $scope.data.length; 
  $scope.$watch("search", function(query){
    $scope.counted = $filter("filter")($scope.data, query).length;
  });
});

Ответ 8

Вы можете сделать это с помощью 2 способа. В шаблоне и в Контроллере. В шаблоне вы можете настроить фильтрованный массив на другую переменную, а затем использовать его так, как хотите. Вот как это сделать:

<ul>
  <li data-ng-repeat="user in usersList = (users | gender:filterGender)" data-ng-bind="user.name"></li>
</ul>
 ....
<span>{{ usersList.length | number }}</span>

Если вам нужны примеры, см. Примеры/демонстрационные примеры фильтров AngularJs