diff --git a/docs/content/guide/filter.ngdoc b/docs/content/guide/filter.ngdoc index cfde1aab..a04ef0a8 100644 --- a/docs/content/guide/filter.ngdoc +++ b/docs/content/guide/filter.ngdoc @@ -87,12 +87,16 @@ This factory function should return a new filter function which takes the input 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. + The following sample filter reverses a text string. In addition, it conditionally makes the text upper-case. - + -
+

No filter: {{greeting}}
Reverse: {{greeting|reverse}}
@@ -101,7 +105,7 @@ text upper-case. - angular.module('myReverseModule', []) + angular.module('myReverseFilterApp', []) .filter('reverse', function() { return function(input, uppercase) { input = input || ''; @@ -116,12 +120,53 @@ text upper-case. return out; }; }) - .controller('Controller', ['$scope', function($scope) { + .controller('MyController', ['$scope', function($scope) { $scope.greeting = 'hello'; }]); + +## 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. + + + +
+ Input:
+ Decoration:
+ No filter: {{greeting}}
+ Reverse: {{greeting | decorate}}
+
+
+ + + 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: '*'}); + +
+ + ## Testing custom filters See the [phonecat tutorial](http://docs.angularjs.org/tutorial/step_09#test) for an example.