Продолжая тему работы с ng-repeat в Ангуляр фреймворк, хочу рассказать о том, как работать с кастомными фильтрами.
Можно вернуться к примеру в прошлой статье, где мы добавили фильтр в ng-repeat, чтобы разобраться с азами. Я немного «доработал» пример. Теперь это уже не список танков, а табличка. И я добавил параметр «год начала производства».
HTML файл стал вот таким:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<!doctype html> <html ng-app="projectRepDemo"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <script id="angularScript" src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script> <script src="/app-js/project.js"></script> </head> <body> <div ng-controller="ngRepDemo as rep"> <label>Список Танков:</label><br /> <input ng-model="s" placeholder="фильтр по названию..." /> <table> <tr> <th>Название</th> <th>Макс. скорость</th> <th>Год начала производства</th> </tr> <tr ng-repeat="elm in rep.list | filter:s" align="center"> <td>{{elm.name}}</td> <td>{{elm.speed}}</td> <td>{{elm.year}}</td> </tr> </table> </div> </body> </html> |
А это код модуля:
1 2 3 4 5 6 7 8 9 10 11 |
angular.module('projectRepDemo', []) .constant('TANKS', [ {name: 'Леопард 2A7 (Германия)', speed: 72, year: 1979}, {name: 'M1A2 (США)', speed: 68, year: 1980}, {name: 'Challenger 2 (Великобритания)', speed: 59, year: 1994}, {name: 'Merkava Mark IV (Израиль)', speed: 64, year: 1978}, {name: 'Танк Т-90МС "Тагил"', speed: 60, year: 2004}] ) .controller('ngRepDemo', function (TANKS) { this.list = TANKS; }); |
В контексте контроллера ngRepDemo выводится таблица танков с помощью директивы ng-repeat. Для связи фильтра и поля ввода используется директива ng-model.
Попробуем ввести в поле число ноль.
Видим, что помимо Т-90МС, фильтру соответствует и танк M1A2, потому что ноль встречается в его данных о годе начала производства. Хотелось бы фильтровать отдельно столбец с названием. Но для этого придется создать и запрограммировать собственный фильтр.
Кастомый фильтр для фильтрации по столбцу
В HTML коде поменяется немного, нужно указать имя фильтра и передать ему нужные параметры.
1 |
<tr ng-repeat="elm in rep.list | filterByName:s" align="center"> |
filterByName — ещё пока не создан. Любой фильтр в качестве первого параметра будет получать список элементов цикла (у нас это rep.list), а дальше через двоеточие вы можете передать дополнительные параметры. У нас таким параметром выступает «s».
Объявим фильтр filterByName в нашем модуле:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
angular.module('projectRepDemo', []) .constant('TANKS', [ ... ]) .controller('ngRepDemo', function (TANKS) { this.list = TANKS; }) .filter('filterByName',function() { return function (items, criterion) { //аккумулятор var tmp = []; if (criterion == undefined || criterion == "") return items; if (items.length > 0) { for (i=0;i<items.length;i++) { var item = items[i]; //проверка критерия if (item.name.indexOf(criterion) != -1) tmp.push(item); } } //вернем новый список return tmp; } }); |
Фильтр — это функция, которая должна возвращать специальную функцию :), которая в свою очередь возвращает список элементов, удовлетворяющих критериям фильтрации.
На входе мы видим два параметра — items и criterion. items — обязательно передаётся в любой кастомный фильтр, а criterion — это дополнительный параметр произвольного типа, и их может быть произвольное число. Ровно столько, сколько вам необходимо.
В нашем случае, в фильтре проверяется название танка на соответствие критерию:
1 |
item.name.indexOf(criterion) != -1) |
В итоге я возвращаю новый список элементов, которые собираются в массиве tmp.
Остаётся лишь опробовать работу фильтра:
Теперь все так, как и хотелось.
Кастомные фильтры не только для циклов
Кастомные фильтры применяются не только в ng-repeat, тогда в качестве первого параметра может быть передан не список, а, к примеру, какая то константа или объект. Так функционируют встроенные фильтры для форматирования вывода даты:
1 2 |
{{'2016-01-15' | date:'dd MMM yyyy'}} //выведет - 15 Jan 2016 |
и валюты:
1 2 |
{{15500 | currency:"$":0 }} //выведет - $15,500 |