The best way to return the number of results from a filtered ngRepeat (ordered or not) is by assigning an alias to it.
Let’s say we have a list of books. We use ngRepeat to output the list like so:
<ul>
<li ng-repeat="book in books">
<p>{{book.title}}</p>
</li>
</ul>
At this point, returning the total number of books in our list would be as simple as referencing {{books.length}}
in our document.
But maybe we have a lot of books on our list, so we add an input field to our document where our user can enter search criteria to narrow it down, as well as a filter to our ngRepeat, based on their input:
<!-- Here's our input field: -->
<input type="text" ng-model="search">
<!-- And here's our now-filtered book list: -->
<ul>
<li ng-repeat="book in books | filter:search">
<p>{{book.title}}</p>
</li>
</ul>
So how do we get the number of books returned by our filter? We could execute the filter again, wherever in our document we wanted to output the information:
<p>Total results: {{ ( books | filter:search ).length }}</p>
But this is the very definition of WET. There’s absolutely no reason to execute the same filter on the same data set on the same page a second time.
Unless, of course, you just really love typing.
Instead, we assign an alias to our filtered result in the ngRepeat line, like so:
<li ng-repeat="book in results = ( books | filter:search )">
Referencing the number of books returned by our filter is as simple as calling {{results.length}}
in our document.
Note: As of Angular 1.3, one can also use an filter:expression as alias_expression
construction in the ngRepeat to assign an alias, like so:
<li ng-repeat="book in books | filter:search as results">
The reference would be the same: {{results.length}}
Now, if we wanted to enable the user to sort the filtered results, we would add a dropdown of sort criteria, then reference it in our ngRepeat using orderBy, like so:
<!-- Our search field -->
<input type="text" ng-model="search">
<!-- Our sort dropdown: -->
<select ng-model="order">
<option value="title">Sort by title</option>
<option value="author">Sort by author</option>
</select>
<!-- Our filtered, sorted book list -->
<ul>
<li ng-repeat="book in books | filter:search | orderBy:order">
<p>{{book.title}}</p>
</li>
</ul>
In order to reference the results (without executing the filter a second time, like some sort of nihilist) we again assign an alias, like so:
<li ng-repeat="book in results = ( books | filter:search | orderBy:order )">
No, we don’t need the orderBy in order to get the number of results (referenced, as before, with {{results.length}}
) but we do need it in order to output our results in the selected order.