What is stateful filtering in AngularJS?

I was reading the AngularJS developer guide on the Filter section (https://docs.angularjs.org/guide/filter#stateful-filters) and came across "Stateful Filters".

This description is given as follows:

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.

I'm new to web development, so have no idea what Stateful filtering is, and Angular Documentation didn't explain it either :( Can someone please explain what is the difference between a normal filter and a stateful filter is?


"State" is referring to variables/properties/etc that are set throughout the application. These values have the potential to change at any given time. The docs are saying that the filter shouldn't depend on external "state". Anything the filter needs to know about should be passed in as an argument when filtering, and the filter should then have everything it needs to do the filtering and return the result Look over the demo in the docs and you'll see that in the "stateful" filter, the filter has a dependency on a service which it uses to do the filtering. That service value could change during a $digest cycle, so the $stateful property has to be set on the filter so that Angular will run the filter again to be sure that dependency hasn't changed state, this changing the filter's result.

So, all "state" should be in the arguments, like this:

<p>{{myData | multiplyBy:multiplier}}</p>

With a filter like:

.filter('multiplyBy', function() {
  function filter(input, multiplier) {
    return input * multiplier;
  }
  return filter;
})

If the data or arguments change, the filter will run again.

The stateful version would be something like this (not recommended!):

<p>{{myData | myFilter}}</p>

And the filter gets it's needed information from external sources:

.filter('myFilter', ['someDependency', function(someDependency) {
  function filter(input) {
    // let's just say `someDependency = {multiplier: 3}`
    return input * someDependency.multiplier;
  }
  filter.$stateful = true;
  return filter;
}])

In that sample filter, someDependency.multiplier should have been passed in as an argument to the filter (as in the first example), rather than being a dependency of the filter.

To further clarify the problem: If you called a function like this: foo(20) and get a result of 40, you should get the same result if you repeat the process. If you called foo(20) again and got 92, that would be rather confusing, right? Assuming foo isn't a function that is made to return random values, the only way it could return different numbers each time is if it performs differently based on a hidden state (something changing internally, rather than being passed in as an argument). The idea that the function would return the same each time given the same arguments is called being "idempotent".

Note: $stateful seems to be new in Angular 1.3