У меня есть массив данных, который содержит много объектов (формат 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
также изменяет значение отображаемых в настоящее время людей. Но этого не происходит. Он всегда отображает полных лиц в данных, а не отфильтрованных - как я могу получить количество отфильтрованных данных?
Для 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
Попробуйте аналогичный пример. Кредиты идут на Павел Козловский
Для полноты, в дополнение к предыдущим ответам (выполнить расчет видимых людей внутри контроллера), вы также можете выполнить эти вычисления в своем 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>
выражение псевдонима предотвратит проблему с несколькими фильтрами.
Я надеюсь, что это поможет.
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
data.length
я использую {{filteredData.length}}
data.length
{{filteredData.length}}
. Я также понял, что myInputModel
- это модель, сопоставленная с входным запросом, который фильтрует данные. val
будет текстом, который вводится во ввод (в основном запрос), но каждый раз, когда я печатаю, он меняется. Но что здесь за filterFilter
? Я мог бы добавить, что у меня есть свой собственный customFilter (в котором я могу указать, какой ключ объекта следует учитывать при фильтрации).
ng-repeat="person in filteredData"
как нет смысла фильтровать его дважды. С помощью службы $filter
вы можете запросить определенный фильтр, просто добавив к нему суффикс «Filter», например: dateFilter
, jsonFilter
и т. Д. Если вы используете свой собственный фильтр, просто используйте его вместо универсального filterFilter
.
Так как AngularJS 1.3 вы можете использовать псевдонимы:
item in items | filter:x as results
и где-нибудь:
<span>Total {{results.length}} result(s).</span>
От docs:
Вы также можете предоставить необязательное выражение псевдонима, которое затем будет хранить промежуточный результаты повторителя после применения фильтров. типично это используется для отображения специального сообщения, когда фильтр активен ретранслятор, но отфильтрованный набор результатов пуст.
Например: элемент в элементах | фильтр: x, поскольку результаты сохранят фрагмент повторяющихся элементов в качестве результатов, но только после элементов были обработаны через фильтр.
$scope.$watch
к этому псевдониму. Какие-нибудь советы для $broadcast
псевдонимов results
?
Также полезно отметить, что вы можете хранить несколько уровней результатов, группируя фильтры
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>
здесь демонстрационная скрипка
Самый простой способ, если у вас
<div ng-repeat="person in data | filter: query"></div>
Отфильтрованная длина данных
<div>{{ (data | filter: query).length }}</div>
Здесь приведен пример См. в 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;
});
});
Вы можете сделать это с помощью 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
filtered.length
внутри моего контроллера? Есть ли способ сделать это?