Sometimes we need to initialize an Angular filter asynchronously. For example, information for filtering might come from a server. Here is how one can do this.
Here is the page setup
initial attempt - does not work
My initial attempt was the most straightforward approach: just return a promise
module.filter callback. After 1 second I would resolve the promise with the actual
Unfortunately, this does not work. Angular tries to parse the expression
'a string' | aFilter
aFilter as a function. But this is not a function, instead it is a promise object!
A different approach is to use an inner worker function inside a filter. This worker function could be replaced at any moment, for example after a timeout of 1 second.
You can see the filter in action at http://jsbin.com/zucunu/2
a string filtered initially
// after 1 second changes to
a string filtered with delayed!!!
Main points in the script:
- We can inject other services into filter registration function
registerAFilter. In this case I injected
- The returned function
tempFilteris the one called by Angular digest cycle over an over. It has access to the actual worker function
initialFilterat first, then points at
$timeoutservice is integrated with digest cycle, thus we did not have to call
$rootScope.$applyafter changing the filter inner function.
- It would make sense to cloak the page until the filters have been resolved to avoid sudden text changes.
This is a solution to delayed filter initialization using available AngularJs services. Instead of implementing promise logic deep in the Angular expression parsing, the framework allows us to change our code inside the filter function.
We only want to initialize the filter once, and then use the result multiple times. Filtering potentially runs multiple times and any async processing per item would lead to bad performance and page flickering.