@ngdoc tutorial @name 11 - Custom Filters @step 11 @description In this step you will learn how to create your own custom display filter. * In the previous step, the details page displayed either "true" or "false" to indicate whether certain phone features were present or not. In this step, we are using a custom filter to convert those text strings into glyphs: ✓ for "true", and ✘ for "false". Let's see what the filter code looks like.
## The `checkmark` Filter Since this filter is generic (i.e. it is not specific to any view or component), we are going to register it in a `core` module, which contains "application-wide" features.
**`app/core/core.module.js`:** ```js angular.module('core', []); ```
**`app/core/checkmark/checkmark.filter.js`:** ```js angular. module('core'). filter('checkmark', function() { return function(input) { return input ? '\u2713' : '\u2718'; }; }); ```
As you may have noticed, we (unsurprisingly) gave our file a `.filter` suffix.
The name of our filter is "checkmark". The `input` evaluates to either `true` or `false`, and we return one of the two unicode characters we have chosen to represent true (`\u2713` -> ✓) and false (`\u2718` -> ✘). Now that our filter is ready, we need to register the `core` module as a dependency of our main `phonecatApp` module.
**`app/app.module.js`:** ```js angular.module('phonecatApp', [ ... 'core', ... ]); ``` ## Templates Since we have created two new files (**core.module.js**, **checkmark.filter.js**), we need to include them in our layout template.
**`app/index.html`:** ```html ... ... ``` The syntax for using filters in AngularJS templates is as follows: ``` {{expression | filter}} ``` Let's employ the filter in the phone details template:
**`app/phone-detail/phone-detail.template.html`:** ```html ...
Infrared
{{$ctrl.phone.connectivity.infrared | checkmark}}
GPS
{{$ctrl.phone.connectivity.gps | checkmark}}
... ``` ## Testing Filters, like any other code, should be tested. Luckily, these tests are very easy to write.
**`app/core/checkmark/checkmark.filter.spec.js`:** ```js describe('checkmark', function() { beforeEach(module('core')); it('should convert boolean values to unicode checkmark or cross', inject(function(checkmarkFilter) { expect(checkmarkFilter(true)).toBe('\u2713'); expect(checkmarkFilter(false)).toBe('\u2718'); }) ); }); ``` The call to `beforeEach(module('core'))` loads the `core` module (which contains the `checkmark` filter) into the injector, before every test. Note that we call the helper function `inject(function(checkmarkFilter) {...})`, to get access to the filter that we want to test. See also {@link angular.mock.inject angular.mock.inject()}.
When injecting a filter, we need to suffix the filter name with 'Filter'. For example, our `checkmark` filter is injected as `checkmarkFilter`. See the [Filters](guide/filter#using-filters-in-controllers-services-and-directives) section of the Developer Guide for more info.
You should now see the following output in the Karma tab: ``` Chrome 49.0: Executed 4 of 4 SUCCESS (0.091 secs / 0.075 secs) ``` ## Experiments
* Let's experiment with some of the {@link api/ng/filter built-in AngularJS filters}. Add the following bindings to `index.html`: * `{{'lower cap string' | uppercase}}` * `{{{foo: 'bar', baz: 42} | json}}` * `{{1459461289000 | date}}` * `{{1459461289000 | date:'MM/dd/yyyy @ h:mma'}}` * We can also create a model with an input element, and combine it with a filtered binding. Add the following to `index.html`: ```html Uppercased: {{userInput | uppercase}} ``` ## Summary Now that we have learned how to write and test a custom filter, let's go to {@link step_12 step 12} to learn how we can use AngularJS to enhance the phone details page further.