forked from angular/angular.js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfilter.ngdoc
177 lines (140 loc) · 6.3 KB
/
filter.ngdoc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
@ngdoc overview
@name Filters
@sortOrder 280
@description
A filter formats the value of an expression for display to the user. They can be used in view templates,
controllers or services and it is easy to define your own filter.
The underlying API is the {@link ng.$filterProvider `filterProvider`}.
## Using filters in view templates
Filters can be applied to expressions in view templates using the following syntax:
{{ expression | filter }}
E.g. the markup `{{ 12 | currency }}` formats the number 12 as a currency using the {@link ng.filter:currency `currency`}
filter. The resulting value is `$12.00`.
Filters can be applied to the result of another filter. This is called "chaining" and uses
the following syntax:
{{ expression | filter1 | filter2 | ... }}
Filters may have arguments. The syntax for this is
{{ expression | filter:argument1:argument2:... }}
E.g. the markup `{{ 1234 | number:2 }}` formats the number 1234 with 2 decimal points using the
{@link ng.filter:number `number`} filter. The resulting value is `1,234.00`.
## Using filters in controllers, services, and directives
You can also use filters in controllers, services, and directives. For this, inject a dependency
with the name `<filterName>Filter` to your controller/service/directive. E.g. using the dependency
`numberFilter` will inject the number filter. The injected argument is a function that takes the
value to format as first argument and filter parameters starting with the second argument.
The example below uses the filter called {@link ng.filter:filter `filter`}.
This filter reduces arrays into sub arrays based on
conditions. The filter can be applied in the view template with markup like
`{{ctrl.array | filter:'a'}}`, which would do a fulltext search for "a".
However, using a filter in a view template will reevaluate the filter on
every digest, which can be costly if the array is big.
The example below therefore calls the filter directly in the controller.
By this, the controller is able to call the filter only when needed (e.g. when the data is loaded from the backend
or the filter expression is changed).
<example module="FilterInControllerModule">
<file name="index.html">
<div ng-controller="FilterController as ctrl">
<div>
All entries:
<span ng-repeat="entry in ctrl.array">{{entry.name}} </span>
</div>
<div>
Entries that contain an "a":
<span ng-repeat="entry in ctrl.filteredArray">{{entry.name}} </span>
</div>
</div>
</file>
<file name="script.js">
angular.module('FilterInControllerModule', []).
controller('FilterController', ['filterFilter', function(filterFilter) {
this.array = [
{name: 'Tobias'},
{name: 'Jeff'},
{name: 'Brian'},
{name: 'Igor'},
{name: 'James'},
{name: 'Brad'}
];
this.filteredArray = filterFilter(this.array, 'a');
}]);
</file>
</example>
## Creating custom filters
Writing your own filter is very easy: just register a new filter factory function with
your module. Internally, this uses the {@link ng.$filterProvider `filterProvider`}.
This factory function should return a new filter function which takes the input value
as the first argument. Any filter arguments are passed in as additional arguments to the filter
function.
The filter function should be a [pure function](http://en.wikipedia.org/wiki/Pure_function), which
means that it should be stateless and idempotent. Angular relies on these properties and executes
the filter only when the inputs to the function change.
<div class="alert alert-warning">
**Note:** filter names must be valid angular expression identifiers, such as `uppercase` or `orderBy`.
Names with special characters, such as hyphens and dots, are not allowed.
</div>
The following sample filter reverses a text string. In addition, it conditionally makes the
text upper-case.
<example module="myReverseFilterApp">
<file name="index.html">
<div ng-controller="MyController">
<input ng-model="greeting" type="text"><br>
No filter: {{greeting}}<br>
Reverse: {{greeting|reverse}}<br>
Reverse + uppercase: {{greeting|reverse:true}}<br>
</div>
</file>
<file name="script.js">
angular.module('myReverseFilterApp', [])
.filter('reverse', function() {
return function(input, uppercase) {
input = input || '';
var out = "";
for (var i = 0; i < input.length; i++) {
out = input.charAt(i) + out;
}
// conditional based on optional argument
if (uppercase) {
out = out.toUpperCase();
}
return out;
};
})
.controller('MyController', ['$scope', function($scope) {
$scope.greeting = 'hello';
}]);
</file>
</example>
## Stateful filters
It is strongly discouraged to write filters that are stateful, because the execution of those can't
be optimized by Angular, which often leads to performance issues. Many stateful filters can be
converted into stateless filters just by exposing the hidden state as a model and turning it into an
argument for the filter.
If you however do need to write a stateful filter, you have to mark the filter as `$stateful`, which
means that it will be executed one or more times during the each `$digest` cycle.
<example module="myStatefulFilterApp">
<file name="index.html">
<div ng-controller="MyController">
Input: <input ng-model="greeting" type="text"><br>
Decoration: <input ng-model="decoration.symbol" type="text"><br>
No filter: {{greeting}}<br>
Decorated: {{greeting | decorate}}<br>
</div>
</file>
<file name="script.js">
angular.module('myStatefulFilterApp', [])
.filter('decorate', ['decoration', function(decoration) {
function decorateFilter(input) {
return decoration.symbol + input + decoration.symbol;
}
decorateFilter.$stateful = true;
return decorateFilter;
}])
.controller('MyController', ['$scope', 'decoration', function($scope, decoration) {
$scope.greeting = 'hello';
$scope.decoration = decoration;
}])
.value('decoration', {symbol: '*'});
</file>
</example>
## Testing custom filters
See the [phonecat tutorial](http://docs.angularjs.org/tutorial/step_09#test) for an example.