AngularJS: My solution to the ng-repeat performance problem

  • AngularJS allows me to get simple things get done very quickly, watch a value for changes and update the views whenever necessary.
  • For one of our projects, vizit.lu (Sorry, the site is no longer available), a map based real-estate search platform, I used AngularJS for the frontend.
  • When ever the user drags the map, the list of estates is updated.
  • The server reponse arrived at the client within 100ms and then the browser took almost a second to render the list and markers on the map, this was not a satisfying user experience.
  • In short, ng-repeat creates bad performance and AngularJS is getting slower with more than 2000-2500 two-way bindings to watch.

Performance of ngRepeat can become quickly very bad for rendering long lists or tables. I tried several solutions to tackle the problem and describe my solution

@praaaw: because performance is everything

AngularJS is great. I started with BackboneJS as frontend MVC, but soon switch to AngularJS because of the concept AngularJS adds to HTML. AngularJS allows me to get simple things get done very quickly, watch a value for changes and update the views whenever necessary.

Further for more complex things AngularJS offers just the right structure for code organization. After some effort to learn to use directives and services, AngularJS forces me to get my code clean. This means after some months of using the framework intensively, if things get complicated I know I am doing something wrong. So I need to rethink what I am doing and often a much simpler solution is found.

For one of our projects, vizit.lu (Sorry, the site is no longer available), a map based real-estate search platform, I used AngularJS for the frontend. Once the initial HTML and scripts are loaded only images and JSON is transferred. When ever the user drags the map, the list of estates is updated. So you only see estates that are in the visible part of the map. We designed the whole stack to be fast and the map feels responsive. Our initial goal was to get the estates on the map and in the list under 400ms.

After some testing, the response times were very satisfying, however the application was blocking for 500-700ms after each refresh of the view. Quickly I stumble upon the problem: ng-repeat. The server reponse arrived at the client within 100ms and then the browser took almost a second to render the list and markers on the map, this was not a satisfying user experience.

I was expecting this bad performance due to the internal working of AngularJS. In short, ng-repeat creates bad performance and AngularJS is getting slower with more than 2000-2500 two-way bindings to watch. But for ng-repeat you often want the items to be rendered and then forget about them as they are not updated from the client side. So no two way binding required. The was also true for us, render the html and forget about the bindings.

I tried several different solutions, so here is what I found:

Notice that limit is a variable in the $scope, so changing it automatically adjusts the number of rendered items. And incrementing limit, only renders the added elements.(The drawn elements in the DOM remain untouched) From StackOverflow question.

The limitTo with Infinite Scrolling plays very neat together with the Track By feature for ng-repeat. So updating only those elements that change and an object id can be passed to identify equal objects. Very nice for ng-animate as only those elements are animated that actually change, play around with it on vizit.lu.

NOTE: when using TRACK BY be sure to add it correctly to the ng-repeat line.

My element now looks like this:

UPDATE: here is my directive if it helps

I’ve read the article and founf it pretty interesting, but I was thinking on how I can improve the performance in my solution.

What I do now is to retrive X element from the database every time I reach the bottom of the list (using infinite scrolling), after that I put the results into an array and with ng-repeat I populate the page; this process is repeated untill all the elements are shown (if the user keeps scrolling down).

What I would like to know is if it’s possible to increase the performance of this “badly-thought” script, into something faster in order to optimize the performances of my app on dated devices.

Thanks for this article! I think the infinite scroll works well but the challenge I’m facing is that I have a search form that is used to filter the collection I’m repeating. The infinite scroll does not show the elements that have not yet been displayed by infinite scroll. How can I implement this so that elements not displayed yet by infinite scroll will be displayed by the filter? Thanks!

I have not tested this and it would be harder to come up with the best solution without seeing the code, but it seems to me it would be simple enough to have the search be performed on the original array, grab the result after filtering and swap the array under infinite scroll. You might have to change the limitTo as the search can potentially return more records than you make visible.

Hi, really useful your post, it helps us to forget limit with ng-repeat when we are printing too many elements on DOM and get far better UX ( improving speed and reactiveness ) in our product, so first of all thanks.

Our product is a complex RIA, and we usually have to reload and reprint elements of the DOM depending of users action. When we started using limitTo in the way you explain, we experience memory leaks and because of that, we had to improve the $destroy phase.

I translate our improvements to your directive. It’s just about manually unbinding and removing the element of the directive when $destroy event is thrown. You can see this solution in the fork I’ve created of your gist in the following URL.

I need your help regarding AngularJS I hope you can help me. I don’t know where I can post the problem. I am totally new to angular and development. I hope you can help me.

My problem is that the objects that I collected from an API webservice won’t display after ng-repeat is perform. I hope you can help me and guide me to right direction.

here’s my codes:

var travelApp = angular.module(‘travelApp’, [‘ngRoute’,’ngResource’]);

controller: ‘HomeCtrl’,

templateUrl: ‘/html/home.html’

controller: ‘HotelCtrl’,

templateUrl: ‘/html/hotel.html’

$scope.title = ‘Home’;

$scope.title = ‘Hotel’;

var result = {};

console.log(obj.data);

console.log(result);

AngularJS: My solution to the ng-repeat performance problem

You might also like More from author

Comments are closed, but trackbacks and pingbacks are open.