Пользовательская фильтрация в AngularJS

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

До этого урока на странице деталей телефона мы писали true или false для того чтобы показать наличие какой-нибудь возможности у телефона. Давайте вместо этого отображать символы  или .


Переключим проект на состояние соответствующее данному шагу:


git checkout -f step-9

По сравнению с предыдущим шагом были внесены следующие изменения.


Помимо пользовательских фильтров есть еще встроенные:
    • {{ "lower cap string" | uppercase }}
    • {{ {foo: "bar", baz: 23} | json }}
    • {{ 1304375948024 | date }}
    • {{ 1304375948024 | date:"MM/dd/yyyy @ h:mma" }}
Можете добавить их в index.html и посмотреть, что будет.
Можно даже создать элемент модели данных с текстовым полем и сделать для него фильтрованный биндинг:
  • <input ng-model="userInput"> Uppercased: {{ userInput | uppercase }}



Пользовательский фильтр

Для того чтобы создать новый фильтр, создадим модуль phonecatFilters и зарегистрируем в нем ваш пользовательский фильтр:
angular.module('phonecatFilters', []).filter('checkmark', function() {
  return function(input) {
    return input ? '\u2713' : '\u2718';
  };
});

Имя фильтра это "checkmark". Аргумент input соответствует значению true или false, и мы возвращаем один из двух юникод символов (\u2713 -> ✓) или (\u2718 -> ✘).

Далее надо зарегистрировать модуль phonecatFilters как зависимость у главного модуля phonecatApp.
...
angular.module('phonecatApp', ['ngRoute','phonecatControllers','phonecatFilters']);
...


Шаблон

Т.к. код фильтра живет в файле app/js/filters.js мы должны подключить его в наш layout template.

...
 <script src="js/controllers.js"></script>
 <script src="js/filters.js"></script>
...

Синтаксис использования фильтров в шаблонах следующий:
{{ expression | filter }}

Использование фильтра:
app/partials/phone-detail.html:
...
    <dl>
      <dt>Infrared</dt>
      <dd>{{phone.connectivity.infrared | checkmark}}</dd>
      <dt>GPS</dt>
      <dd>{{phone.connectivity.gps | checkmark}}</dd>
    </dl>
...

Тест

Фильтры как и любой другой компонент надо тестировать:
describe('filter', function() {

  beforeEach(module('phonecatFilters'));

  describe('checkmark', function() {

    it('should convert boolean values to unicode checkmark or cross',
        inject(function(checkmarkFilter) {
      expect(checkmarkFilter(true)).toBe('\u2713');
      expect(checkmarkFilter(false)).toBe('\u2718');
    }));
  });
});

Мы должны вызвать beforeEach(module('phonecatFilters')) перед тем как запускать любой тест проверяющий фильтры. Таким образом мы загружаем модуль phonecatFilters в инжектор для запуска этого теста.

Также мы вызвали вспомогательную функцию inject(function(checkmarkFilter) { ... }) чтобы получить доступ к фильтру, который хотим протестировать. Смотрите angular.mock.inject().

Суффикс 'Filter' добавляется к имени фильтра при внедрении.

Karma должна выдать такой результат тестирования:
Chrome 22.0: Executed 4 of 4 SUCCESS (0.034 secs / 0.012 secs)