AngularJS really slow at rendering with about 2000 elements?
Asked Answered
P

8

27

Here's the fiddle: http://jsfiddle.net/D5h7H/7/

It renders the following:

<div ng-repeat="group in Model.Groups">
    <span>{{group.Name}}</span>
    <div ng-repeat="filter in group.Filters">
        <input type="checkbox" ng-model="filter.enabled">{{filter.Name}}
        <select ng-disabled="!filter.enabled">
            <option ng-repeat="value in filter.Values">{{value}}</option>
        </select>
    </div>
</div>

It's a list of filters that is loaded in json from the server and then rendered to the user (in an example json is generated right there in Fiddle). At the moment there are 6 groups of 30 filters in each with 15 option elements for each filter.

In Firefox it now takes about 2 seconds to redraw the UI.

Is this time ok for angular js? Is there anything I'm doing wrong that caused 2sec. rendering (cause 2000 elements doesn't look as a big number to me, but 2sec. is certainly big)?

Percolation answered 3/3, 2013 at 6:33 Comment(4)
Takes less than one second in chrome latest stable. So the problem is not for every browser.Occupy
Have you tried using a profiler to see where there are hot spots?Daley
I haven't tried it in profiler, I'm new to Angular. Also, the time just proportionally increases when I generate more filters, so it would be hard for me to find the spot.. So mainly the question was about - is this an expected thing from Angular or not?Percolation
Create a directive and inject your own html. You lose a lot of the Angular benefits but it renders MUCH faster.Rostellum
G
28

In AngularJS 1.3+, there is One-time binding built-in:

The main purpose of one-time binding expression is to provide a way to create a binding that gets deregistered and frees up resources once the binding is stabilized. Reducing the number of expressions being watched makes the digest loop faster and allows more information to be displayed at the same time.

In order to make the one-time binding, prepend :: to the binding value:

<div>{{::name}}</div> 

Also see relevant discussions:

Galsworthy answered 8/9, 2014 at 23:4 Comment(2)
As this is a one time binding, does this mean that the initial rendering of the elements will not be any faster? As the binding is required for the first pass of interpolation.Floury
Also using track by within the ng-repeat should greatly improve performance.Waitress
A
15

You should look at bindonce if you don't need to update the UI after the data has been bound to it. bindonce can also wait until an object has been loaded and then do the binding. It will save you a bunch of time and reduce your $watch()es dramatically when used right.

Ambary answered 16/9, 2013 at 17:44 Comment(1)
As answered by alecxe, a bind-once feature is built into Angular 1.3+. You prepend :: to the binding value.Modillion
A
4

That's due to how AngularJS does dirty checking. Here's a definitive answer to slow rendering with AngularJS.

Alcmene answered 3/3, 2013 at 16:36 Comment(0)
S
4

Using this project: angular-vs-repeat will boost up your performance.

With this, the browser will render (thus angular will do its dirty-checking) to only so many elements that fit in the scrollable container where you render the elements. Demo here

Sterile answered 27/5, 2014 at 11:36 Comment(0)
H
1

I realize this is an old question but I don't think an answer has been posted yet.

I believe the reason your form is slow is not just that you have 2,000+ elements but that those elements are form elements using ng-model. The built in form validation in Angular is very powerful and convenient but can behave very slowly especially when you first load the form. If those 180(6x30) input elements used something like ng-checked instead of ng-model, avoiding form validation mechanism, then you form should load much faster.

<input type="checkbox" ng-checked="filter.enabled">{{filter.Name}}

Reducing watchers with one-time binding via :: will also help the situation but I think your main issue is with ng-model and angular form validation.

Hughs answered 31/10, 2016 at 18:57 Comment(0)
P
1

With about 2000 items to load, you needn't to render them all at once. You can aggressively render them when page scroll, or change page. Refer to this question

Use unique id such as filter id to minimize the time of ng-repeat's creation of all the dom. Refer to tracking-and-duplicates

As the answer of alecxe above, use one-time bounding, if that not proper for you, you can slow the digest frequency with such ng-model-options="{ debounce: 200 } angular option settings

And last, you have to use some performance analyser tools to track the bottleneck of the application, and fix them.

Hope this helps.

ng-repeat="filter in group.Filters | track by:filter.id | limitTo: NumPerOperation"
Papism answered 16/11, 2016 at 11:19 Comment(0)
B
0

Using these two angular modules you can make the renderization of your tables much faster.

"quick-ng-repeat" https://github.com/allaud/quick-ng-repeat

"infinite-scroll" https://github.com/infinite-scroll/infinite-scroll

Just be aware this is not a solution to improve the performance of your "ng-repeat", this is just a different approach to make your tables faster.

Burchell answered 25/10, 2015 at 19:16 Comment(0)
E
-2

Substitute ng-repeat="group in Model.Groups" with collection-repeat="group in Model.Groups".

Entryway answered 9/10, 2015 at 19:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.