There is a common question I get time to time, so I decided to write about it here.
Let’s say I have an array of people and I filter them on a
ng-repeat, then I want to access that filtered result to do something. I can imagine a few different use cases:
- See how many items matched your search to recalculate your pagination.
- Change the template based on the number of results you have.
- Display a message if you got no results.
- Show the quantity of items returned from your search.
Let’s start with our controller:
1 2 3
And then our html:
1 2 3 4 5 6 7 8 9 10 11
Uhm, it doesn’t update the number of filtered people… It keeps saying 6 no matter what. Also, if there is no result, I wanted to see any message, at least to know that I got no results and it is not an error.
Ok, I hear you, but how can we achieve that? Well, we can’t do a
length on the original array, it never changes. What if we create a new array that hold only the filtered people? Yeah, why not? We could create some method on our controller to do the filtering and then iterate over it with
ng-repeat. That is fine but that defeats the purpose of our nifty HTML with no extra code for filtering. Can’t we do better? Yeah, let’s see:
1 2 3 4 5 6 7 8 9 10 11 12
What’s going on here? We are creating that new array directly on the HTML. The idea can be read as follow: Filter our
people array, save the result on a new
filteredPeople array and finally, iterate over it.
What’s the advantage here? That we can access our
filteredPeople where we need it, both in our HTML and controller. Having that in mind, we can now access its
length property to show a message if there are no results and even to count the number of filtered people.
But what are the disadvantage?
filteredPeople is going to be evaluated in every
$digest and on a big big list it can be problematic and then is when we should consider doing the filtering on the controller.
That is all. A nice trick for a really common problem that comes useful on small to medium lists.