AngularJS: Count Filtered Items
Я показываю подмножества списка, если флажок установлен. Я хотел бы заменить X рядом с флажком с подсчетом списка, соответствующего критериям выбора. У меня есть плункер, который делает все, кроме подсчета подмножества здесь.
Мой контроллер выглядит следующим образом:
var app = angular.module('app', []);
app.controller('MainController', function($scope){
$scope.cbMarvel = true;
$scope.cbDCComics = true;
$scope.heroes = [
{
id: 1,
name: 'Iron Man',
fname: 'Tony',
lname: 'Stark',
location: 'Stark Tower',
comic: 'Marvel'
},
{
id: 2,
name: 'Batman',
fname: 'Bruce',
lname: 'Wayne',
location: 'Bat Cave',
comic: 'DC'
},
{
id: 3,
name: 'Superman',
fname: 'Clark',
lname: 'Kent',
location: 'Metroplis',
comic: 'DC'
},
{
id: 1,
name: 'Daredevil',
fname: 'Jack',
lname: 'Murdock',
location: 'Court Room',
comic: 'Marvel'
},
{
id: 5,
name: 'Flash',
fname: 'Barry',
lname: 'Allen',
location: 'Speedline',
comic: 'DC'
},
{
id: 6,
name: 'Hulk',
fname: 'Bruce',
lname: 'Banner',
location: 'Labratory',
comic: 'Marvel'
},
{
id: 7,
name: 'Hawkeye',
fname: 'Clint',
lname: 'Barton',
location: 'Nest',
comic: 'Marvel'
},
{
id: 8,
name: 'Thor',
fname: 'Donald',
lname: 'Blake',
location: 'Asgard',
comic: 'Marvel'
}
];
});
И мой взгляд выглядит так:
<!DOCTYPE html>
<html ng-app="app">
<head>
<link data-require="[email protected]*" data-semver="3.2.0" rel="stylesheet" href="#" onclick="location.href='https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.css'; return false;" />
<link data-require="[email protected]*" data-semver="3.2.0" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" />
<script data-require="[email protected]*" data-semver="3.2.0" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.js"></script>
<script data-require="[email protected] current" data-semver="2.0.3" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script data-require="[email protected]" data-semver="1.2.20" src="https://code.angularjs.org/1.2.20/angular.js"></script>
<script data-require="[email protected]*" data-semver="0.11.0" src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.0.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="MainController">
<fieldset>
<legend>Comments Log</legend>
<div class="row">
<div class="col-md-4">
<input type="checkbox" ng-model="cbMarvel"/> Marvel [X]
</div>
<div class="col-md-4"> </div>
<div class="col-md-4">
<input type="checkbox" ng-model="cbDCComics"/> DC Comics [X]
</div>
</div>
<div class="row"> </div>
<div class="row col-md-10">
<div ng-if="heroes.length == 0"><b>No Heroes Found!</b>
</div>
<div ng-repeat="h in heroes | filter:{comic:'Marvel'}" ng-show="cbMarvel">
{{ h.name}} - {{h.comic}}
</div>
<div ng-repeat="h in heroes | filter:{comic:'DC'}" ng-show="cbDCComics">
{{ h.name}} - {{h.comic}}
</div>
</div>
</fieldset>
</body>
</html>
Ответы
Ответ 1
Вы можете установить этот счет в самой модели представления при связывании данных или просто иметь метод в области, возвращающей счет.
app.controller('MainController', function($scope, filterFilter){
....
$scope.getCount = function(strCat){
return filterFilter( $scope.heroes, {comic:strCat}).length;
}
...
});
и использовать его как: -
Marvel [{{getCount("Marvel")}}]
.....
DC Comics [{{getCount("DC")}}]
Plnkr
Если список не меняется, когда вы находитесь на странице, я бы предложил узнать длину и привязать ее к свойству в самой модели представления и использовать ее в представлении.
//Set your data model
$scope.cbMarvel = {value:true, count:getCount('Marvel')};
$scope.cbDCComics = {value:true, count:getCount('DC')};
и на ваш взгляд
<input type="checkbox" ng-model="cbMarvel.value"/> Marvel [{{cbMarvel.count}}]
Plnkr2
Если ваш набор данных огромен, вместо использования фильтра внутри getCount используйте forEach и каждый раз заполняйте счетчик для каждого типа.
Infact вам вообще не нужен фильтр, кажется, неэффективно перебирать один и тот же список, используя фильтр в вашем случае. Ваш статический список так категоризирует его в самом контроллере.
var comics = $scope.comics = {}; //Dictionary of comics
//Create the collection here.
angular.forEach(heroes, function(itm){
if(!comics[itm.comic]){
comics[itm.comic] = {name:itm.comic, value:true, count:1, items:[itm] };
return;
}
comics[itm.comic].count++; //Incr count
comics[itm.comic].items.push(itm); //push specific item
});
и удалите все фильтры в вашем представлении и выполните: -
<div ng-repeat="h in comics.Marvel.items" ng-show="comics.Marvel.value">
{{ h.name}} - {{h.comic}}
</div>
<div ng-repeat="h in comics.DC.items" ng-show="comics.DC.value">
{{ h.name}} - {{h.comic}}
</div>
Plnk3 - лучший
Ответ 2
Предполагая, что ваш список людей находится в переменной данных, и вы фильтруете людей, использующих модель запросов, следующий код будет работать для вас:
- Число видимых людей:
{{(data|filter:query).length}}
- Общее количество людей:
{{data.length}}
Резюме
{{data.length}}
- печатает общее количество людей
{{(data|filter:query).length}}
- печатает отфильтрованное количество людей
Ответ 3
Возможное решение 1: Inline
Фактически вы можете сохранить ссылку на отфильтрованные результаты в переменной: h in filtered.marvel = (heroes | filter:{comic:'Marvel'})
, которую вы можете использовать так: filtered.marvel.length
.
Смотрите: Plunkr
Возможное решение 2: В контроллере
Вы также можете перенести этот код на свой контроллер:
$scope.filteredHeroes.marvel = $filter('filter')($scope.heroes, {comic:'Marvel'});
который вы можете использовать с помощью ng-repeat="hero in filteredHeroes.marvel"
и {{filteredHeroes.marvel.length}}
(Не забудьте добавить $filter в качестве зависимости от контроллера)
Смотрите: Plunkr
Ответ 4
Чтобы найти объекты count, я использую <scope_obj>.length
в шаблоне .html
.
Здесь мой контроллер:
conciergeControllers.controller('GuestMsgPreviewCtrl', ['$scope', 'GuestMessages',
function($scope, GuestMessages) {
$scope.guests = GuestMessages.query();
}]);
И шаблон (каждый гостевой объект имеет атрибут сообщений, который является объектом массива, поэтому .length
возвращает количество вложенных объектов message
:
<ul ng-repeat="guest in guests">
<li>[[ guest.messages.length ]]</li>
</ul>