AngularJS – ngRepeat Performance Watchers

AngularJS has a directive “ng-repeat” which is very widely used. ng-repeat is used in almost every application but if not used properly can cause various performance issues.

$watch and ng-repeat

The main problem with ng-repeat ism it creates to many watch expression. To understand what is are watches read here.

Lets take a small example

  
<div ng-repeat='item in array'>
       
{{item.name}} — {{item.date}}
  
</div>
  

Suppose if the length of above array is 10, then this ngRepeat creates 10*2 + 1 $watches in angularjs. As you can see such a simple ng-repeat casues 21 watches, anything more complex and with a larger array size will easily add a lot of $watches. On a desktop application this won’t cause any significant slow down, but on mobile application it does slow down the application. On a single page, more than 2000 watches is generally considered bad. Lets see what are the various solution

Easy tips first

ng-repeat track by

ng-repeat has a attribute “track by” with which we can supply a unique id. This reduces the number of dom repaints and dirty checking needed.

  
<div ng-repeat='item in array track by $index'>
  
</div>
  

track by can use any unique id, $index is the most easy one to use. Read More Here

ng-repeat filter

Avoid using ng-repeat filter, it better to pass a filtered array to ng-repeat than using filter

ng-repeat with function

  
<div ng-repeat='item in getArray()'></div> <!- Don't use this ->
  

It always better to use array as a variable rather than returning it from a function.

Batarang

Batarang is a very useful chrome plugin which allows you to see the number of watches, scope model etc. It show which watchExpression is taking most amount of time. This is a very useful tool for debugging. Below are screenshots to see batarang in action.

One Time Watches

One time watches, these are directives/expression which execute $watch only one and then get removed from scope. There are various ways of doing this

Bindone

Bindonce is a great library https://github.com/Pasvaz/bindonce which removes all watches from your ng-repeat. You need to use some custom directives like bo-if, bo-show, bo-html etc. This is a must use library for ng-repeat with large data sets. Go through its documentation and understand how to use it.

Watch Fighters

Watch Fighter is another great library with a custom set of directives https://github.com/abourget/abourget-angular which has a custom set of directives for one time watches.

:: notation in angularjs

angularjs 1.3 introduced :: notation for one time binding.

  
<div ng-repeat='item in ::array'>
        
{{::item.name}} — {{::item.date}}
  
</div>
  

Your Custom Watchers

If you are using custom watchers in your application, then you stop watches by calling their return function. As seen below.

  
var watcher = $scope.$watch('variable',function(newVal,oldVal){
  
});
  
$scope.stop = function(){
    
watcher();
  
};
  

Here is the full code for this

excellence-social-linkdin
excellence-social-facebook
excellence-social-instagram
excellence-social-skype