Last active
August 29, 2015 14:23
-
-
Save pcheek/87d612bd50e10d896267 to your computer and use it in GitHub Desktop.
Significantly improve the performance of list groups in an AngularJS app by replacing nested ngRepeat directives with $index tracking and conditional comparisons.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- | |
AngularJS List Group Performance Improvements | |
Suppose you have an array of items which you would like to group by date. | |
One of the most straightforward approachs to achieving grouped items is to | |
use nested ng-repeat directives and the groupBy filter in angular-filter: | |
https://github.com/a8m/angular-filter#groupby | |
Here is an example: | |
--> | |
<div ng-repeat="(date, dailyItems) in filteredItems = | |
(items | filter: someFilter | groupBy: 'date' | | |
toArray: true | orderBy: 'date')"> | |
<div class="date"> | |
{{dailyItems.$key | date: 'EEEE, MMMM d, yyyy'}} | |
</div> | |
<div class="item" ng-repeat="item in dailyItems"> | |
[...] | |
</div> | |
</div> | |
<!-- | |
However, when coupled with additional filters, and the requirement that | |
orderBy also be used to correctly order the groups of items, you will | |
find that performance decreases significantly as a result of the nested | |
ng-repeat directives and the number of watches that are bound to the view. | |
Leveraging the additional performance benefits of 'track by' augmentation | |
for ngRepeat, we can compare the loop's current item with the previous | |
item in the loop. Simply, if the current item does not have the same date | |
as the previous item, render a new "group". Since the items have not been | |
grouped in a nested array, there may not be a need for the orderBy filter. | |
Here is an example: | |
--> | |
<div ng-repeat="item in filteredItems = | |
(items | filter: someFilter | orderBy: 'date') | |
track by $index"> | |
<div | |
class="date" | |
ng-if="item.date != filteredItems[$index-1].date"> | |
{{item.date | date: 'EEEE, MMMM d, yyyy'}} | |
</div> | |
<div class="item"> | |
[...] | |
</div> | |
</div> | |
<!-- | |
Although this solution may not meet the needs of more complicated use | |
cases, by removing the angular-filter dependency as well as the second | |
ng-repeat directive we were able to improve performance significantly. | |
--> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment