2014-02-06 13:33:42 +00:00
|
|
|
@ngdoc tutorial
|
2016-03-27 21:32:36 +03:00
|
|
|
@name 11 - Custom Filters
|
2014-02-17 13:25:50 +01:00
|
|
|
@step 11
|
2012-03-30 14:02:26 -07:00
|
|
|
@description
|
|
|
|
|
|
2012-04-28 22:45:28 -07:00
|
|
|
<ul doc-tutorial-nav="11"></ul>
|
2012-03-30 14:02:26 -07:00
|
|
|
|
|
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
In this step you will learn how to create your own custom display filter.
|
2014-04-04 14:05:24 +01:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
* 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.
|
2012-03-30 14:02:26 -07:00
|
|
|
|
|
|
|
|
|
2012-04-28 22:45:28 -07:00
|
|
|
<div doc-tutorial-reset="11"></div>
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2014-04-04 14:05:24 +01:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
## The `checkmark` Filter
|
2014-04-04 14:05:24 +01:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
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.
|
2014-04-04 14:05:24 +01:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
<br />
|
|
|
|
|
**`app/core/core.module.js`:**
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
angular.module('core', []);
|
2014-04-04 14:05:24 +01:00
|
|
|
```
|
|
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
<br />
|
|
|
|
|
**`app/core/checkmark/checkmark.filter.js`:**
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
```js
|
|
|
|
|
angular.
|
|
|
|
|
module('core').
|
|
|
|
|
filter('checkmark', function() {
|
|
|
|
|
return function(input) {
|
|
|
|
|
return input ? '\u2713' : '\u2718';
|
|
|
|
|
};
|
|
|
|
|
});
|
2014-04-04 14:05:24 +01:00
|
|
|
```
|
2014-09-10 22:52:32 +01:00
|
|
|
|
2014-04-24 10:59:04 +01:00
|
|
|
<div class="alert alert-info">
|
2016-03-27 21:32:36 +03:00
|
|
|
As you may have noticed, we (unsurprisingly) gave our file a `.filter` suffix.
|
2014-04-24 10:59:04 +01:00
|
|
|
</div>
|
|
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
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` -> ✘).
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
Now that our filter is ready, we need to register the `core` module as a dependency of our main
|
|
|
|
|
`phonecatApp` module.
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
<br />
|
|
|
|
|
**`app/app.module.js`:**
|
2014-02-06 14:02:18 +00:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
```js
|
|
|
|
|
angular.module('phonecatApp', [
|
|
|
|
|
...
|
|
|
|
|
'core',
|
|
|
|
|
...
|
|
|
|
|
]);
|
2014-02-06 14:02:18 +00:00
|
|
|
```
|
2012-03-30 14:02:26 -07:00
|
|
|
|
|
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
## Templates
|
2014-04-04 14:05:24 +01:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
Since we have created two new files (**core.module.js**, **checkmark.filter.js**), we need to
|
|
|
|
|
include them in our layout template.
|
2014-02-06 14:02:18 +00:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
<br />
|
|
|
|
|
**`app/index.html`:**
|
2013-10-11 16:07:43 -07:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
```html
|
|
|
|
|
...
|
|
|
|
|
<script src="core/core.module.js"></script>
|
|
|
|
|
<script src="core/checkmark/checkmark.filter.js"></script>
|
|
|
|
|
...
|
2014-02-06 14:02:18 +00:00
|
|
|
```
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2017-01-24 17:23:54 +00:00
|
|
|
The syntax for using filters in AngularJS templates is as follows:
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2014-02-06 14:02:18 +00:00
|
|
|
```
|
2016-03-27 21:32:36 +03:00
|
|
|
{{expression | filter}}
|
2014-02-06 14:02:18 +00:00
|
|
|
```
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
Let's employ the filter in the phone details template:
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
<br />
|
|
|
|
|
**`app/phone-detail/phone-detail.template.html`:**
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
```html
|
|
|
|
|
...
|
|
|
|
|
<dl>
|
|
|
|
|
<dt>Infrared</dt>
|
|
|
|
|
<dd>{{$ctrl.phone.connectivity.infrared | checkmark}}</dd>
|
|
|
|
|
<dt>GPS</dt>
|
|
|
|
|
<dd>{{$ctrl.phone.connectivity.gps | checkmark}}</dd>
|
|
|
|
|
</dl>
|
|
|
|
|
...
|
2014-05-31 09:28:09 -07:00
|
|
|
```
|
|
|
|
|
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2018-02-27 17:33:42 +01:00
|
|
|
## Testing
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
Filters, like any other code, should be tested. Luckily, these tests are very easy to write.
|
2014-02-06 14:02:18 +00:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
<br />
|
|
|
|
|
**`app/core/checkmark/checkmark.filter.spec.js`:**
|
2014-05-31 17:37:54 -04:00
|
|
|
|
2014-02-06 14:02:18 +00:00
|
|
|
```js
|
2016-03-27 21:32:36 +03:00
|
|
|
describe('checkmark', function() {
|
2012-04-27 15:18:54 -07:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
beforeEach(module('core'));
|
2012-04-27 15:18:54 -07:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
it('should convert boolean values to unicode checkmark or cross',
|
|
|
|
|
inject(function(checkmarkFilter) {
|
|
|
|
|
expect(checkmarkFilter(true)).toBe('\u2713');
|
|
|
|
|
expect(checkmarkFilter(false)).toBe('\u2718');
|
|
|
|
|
})
|
|
|
|
|
);
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
});
|
|
|
|
|
```
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
The call to `beforeEach(module('core'))` loads the `core` module (which contains the `checkmark`
|
|
|
|
|
filter) into the injector, before every test.
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
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()}.
|
2012-04-27 15:18:54 -07:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
<div class="alert alert-info">
|
|
|
|
|
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.
|
|
|
|
|
</div>
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
You should now see the following output in the Karma tab:
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
```
|
|
|
|
|
Chrome 49.0: Executed 4 of 4 SUCCESS (0.091 secs / 0.075 secs)
|
|
|
|
|
```
|
2012-03-30 14:02:26 -07:00
|
|
|
|
|
|
|
|
|
2018-02-27 17:33:42 +01:00
|
|
|
## Experiments
|
2012-04-27 15:18:54 -07:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
<div></div>
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2017-01-24 17:23:54 +00:00
|
|
|
* Let's experiment with some of the {@link api/ng/filter built-in AngularJS filters}.
|
2016-03-27 21:32:36 +03:00
|
|
|
Add the following bindings to `index.html`:
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
* `{{'lower cap string' | uppercase}}`
|
|
|
|
|
* `{{{foo: 'bar', baz: 42} | json}}`
|
|
|
|
|
* `{{1459461289000 | date}}`
|
|
|
|
|
* `{{1459461289000 | date:'MM/dd/yyyy @ h:mma'}}`
|
2012-03-30 14:02:26 -07:00
|
|
|
|
|
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
* We can also create a model with an input element, and combine it with a filtered binding.
|
|
|
|
|
Add the following to `index.html`:
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
```html
|
|
|
|
|
<input ng-model="userInput" /> Uppercased: {{userInput | uppercase}}
|
|
|
|
|
```
|
2012-03-30 14:02:26 -07:00
|
|
|
|
|
|
|
|
|
2018-02-27 17:33:42 +01:00
|
|
|
## Summary
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
Now that we have learned how to write and test a custom filter, let's go to {@link step_12 step 12}
|
2017-01-24 17:23:54 +00:00
|
|
|
to learn how we can use AngularJS to enhance the phone details page further.
|
2012-03-30 14:02:26 -07:00
|
|
|
|
|
|
|
|
|
2012-04-28 22:45:28 -07:00
|
|
|
<ul doc-tutorial-nav="11"></ul>
|