Все о пользовательских фильтрах в AngularJS
Фильтры Ангуляра - одни из самых концептуально сложных элементов в нем. Они немного неправильно поняты и от них мой мозг практически вскипал, пока я изучал их. Фильтры безумно классные, они очень мощны для легкой трансформации наших данных в повторно используемые и масштабируемые кусочки.
Перво-наперво лучше всего понять, что мы вообще хотим изучить. Чтобы сделать это, нам нужно понять, что из себя представляют фильтры и как мы можем их использовать. Я считаю, что есть 4 типа фильтров. Да, 4, но конечно могут быть и другие варианты. Давайте побыстрее с ними справимся.
Фильтр 1: Фильтр для однократного использования (статичный)
Фильтр 1 обрабатывает только один кусок модели данных (не в цикле или чем-нибудь еще более фантастичным) и выплевывает результат в наш вид. Это может быть чем-то типа даты:
<p>{ { 1400956671914 | date: 'dd-MM-yyyy' } }</p>
После преобразования, DOM будет выглядеть так:
<p>24-05-2014</p>
Итак, как нам создать такой же фильтр или нечто похожее?
Давайте возьмем, к примеру, мое полное имя. Если мне нужно быстро применить фильтр и сделать имя заглавными буквами, какое бы решение вы применили?
У Ангуляра есть метод .filter()
для каждого модуля, что для нас означает возможность создания собственных фильтров. Давайте посмотрим на урезанный код фильтра:
|
|
Как вы видите, мы можем назвать наш фильтр и возвратить функцию. Что, черт возьми, происходит? Возвращенная функция вызывается, в то время, когда Ангуляр вызывает фильтры, которые означают двустороннее связывание для наших фильтров.
Пользователь вносит изменения, фильтр снова обрабатывает данные и обновляет их при необходимости. Имя нашего фильтра - это то, как мы можем на него ссылаться внутри биндингов Ангуляра.
Давайте заполним его некоторыми данными:
|
|
Итак, что же это значит? Я прокомментирую:
В качестве примера приложения:
|
|
|
|
Когда мы объявляем его в HTML:
Вот и все, jsFiddle link
Фильтр 2: Фильтры для ng-repeat
Фильтры отлично подходят для потоковой обработки данных и без какой-либо дополнительной работы мы можем сделать именно это.
Синтаксис достаточно похож с предыдущим фильтром, когда мы фильтруем ng-repeat
, возьмем немного данных для примера:
|
|
Мы можем установить обычный ng-repeat
в него:
|
|
Добавьте фильтр, названный startsWithA
, где мы только хотим показать имена в Array массиве, начинающиеся с А:
|
|
Давайте создадим новый фильтр:
|
|
Итак, здесь происходят 2 разных вещи!
Во-первых, предыдущий item
- теперь items
, являющийся нашим массивом из ng-repeat
.
Вторая вещь - это то, что нам нужно вернуть НОВЫЙ массив.
Откомментированный код:
В Версия ES5, используя Array.prototype.filter
для супер чистого кода фильтра:
Вот и все, jsFiddle link
##Фильтр 3: Фильтры для ng-repeat с аргументами
Все тоже самое, что и выше, но мы можем передать аргументы в функции из других моделей. Давайте создадим пример того, что вместо “фильтрации по букве А”, мы можем дать пользователю возможность решать.
Здесь я передаю в фильтр значение модели letter
из ng-model="letter"
. Как он привязывается внутри пользовательского фильтра?
|
|
Самое главное - это запомнить как мы передаем в аргументы! Обратите внимание: letter
сейчас существует внутри return function (items, letter) {}
? Это непосредственно соответствует части :letterpart
. Это значит, что мы можем передавать ровно столько аргументов, сколько нужно (пример):
|
|
Мы бы получили что-то вроде этого:
|
|
Вот и все, jsFiddle link
Фильтр 4: Controller/$scope Фильтр
Этот вариант немного хитрый и я бы использовал его только, если вам на самом деле просто НЕОБХОДИМО его использовать. Мы пользуемся синтаксисом :arg
и передаем функцию $scope
в filter
объект Ангуляра!
Разница этого типа фильтров в том, что объявленные функции и являются тем, что передается внутрь функции фильтра, так что мы, технически, пишем функцию, которая передается в нашу возвращаемую функцию. Мы не получаем доступ к нашему массиву, только в индивидуальному элементу. Важно это запомнить!
Давайте создадим другую функцию, которая фильтрует по букве W
. Для начала, давайте определим функцию в контроллере:
|
|
Затем повтор:
Эти функции, очевидно, ограничены областью видимости и не могут повторно использоваться в других местах. Если это имеет смысл, тогда используйте эту конструкцию, иначе не надо.
Вот и все, jsFiddle link