Loading …
There was an error loading this resource. Please try again later.
 Improve this Doc

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.

Reset the workspace to step 11.

git checkout -f step-11

Refresh your browser or check out this step online: Step 11 Live Demo.

The most important changes are listed below. You can see the full diff on GitHub.

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:

angular.module('core', []);


app/core/checkmark/checkmark.filter.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:

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:

...
<script src="core/core.module.js"></script>
<script src="core/checkmark/checkmark.filter.js"></script>
...

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:

...
<dl>
  <dt>Infrared</dt>
  <dd>{{$ctrl.phone.connectivity.infrared | checkmark}}</dd>
  <dt>GPS</dt>
  <dd>{{$ctrl.phone.connectivity.gps | checkmark}}</dd>
</dl>
...

Testing

Filters, like any other code, should be tested. Luckily, these tests are very easy to write.


app/core/checkmark/checkmark.filter.spec.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 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 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 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:

    <input ng-model="userInput" /> Uppercased: {{userInput | uppercase}}

Summary

Now that we have learned how to write and test a custom filter, let's go to step 12 to learn how we can use AngularJS to enhance the phone details page further.