In the discussion below this article there's a comment by Renan Cakirerk to the effect that, according to an Angular developer, Angular UI performance might degrade beyond 2000 data-bound objects.
It made me seriously consider whether pursuing my non-trivial app with Angular is a good idea. A good app is a fast app after all. I don't want to invest months building something to be bitten at the end.
I am interested in hearing from Angular non-trivial app builders about
It's too much of a risk to wait for the possible "ES6 power and perf boons like Object.observe
" and future versions that will might developers more fine-grained control on the $apply
/ $digest
cycle so that $scope
-limited dirty-checking can be triggered" (Brian Frichette mentions these in the same discussion). I want to know that complex apps can be fast today on v1.2.15.
More details about my problem/solution...
I'm building an app with very rich functionality, where each object (eg user) has many functions that can be done to it, eg linking them to other users, changing their properties, sending them messages, etc.
The spec has upwards of 20 functions on this object: droppable zones, context sensitive toolbar icons (eg the way Word has mini-toolbars that appear near the mouse when you select some text).
These options need to hide and show based on certain mouse actions, like hovering and dragging, and depend on the state of the particular user object (many icons and drop options will show in some circumstances and not others)
Now, the way I've started building this is to have each individual icon and drop area, drag handle, etc as a separate data-bound element with an ng-show (or similar) that's keyed into our custom business logic.
Eg
<user>
<menuicon1 ng-show="business-logic1"/>
<menuicon2 ng-show="business-logic2"/>
<dropzone1 ng-show="business-logic3"/>
<draghandle ng-show="business-logic4"/>
<changessavedicon ng-show="business-logic5"/>
.....
</user>
Assuming the 2000 theoretical limit above is to be feared, then 20 custom showable hideable bits means 100 users (shown using the amazing ng-repeat) is my limit! Maybe showing 100 is silly and I can attack this with filtering etc, but it seems to me that dividing by 20 drastically reduces my object "bandwidth". And what happens when the boss wishes to add 10 more functions?
If I were doing this the jQuery way, I'd probably construct and destroy many of the icons and menu items as needed. Slightly less responsive per hover/drag, but at least the app can scale the number of objects that way.
We can also optimize the performance by running our code outside the Angular zone. In Angular Pipes are used to format data. Using a pipe is also more performant. There are two types of pipes, pure and impure. By default, a pipe is “ pure ”.
And as you’ve probably already guessed, the most common Angular performance issue is in the first option - Angular load performance. But, no Angular application is immune to runtime performance.
Angular load performance refers to how long it takes for a browser to download your application, load it into the browser, parse the JavaScript and get it displayed to your user. Once it’s loaded, the next type of performance is runtime performance. Is your Angular app snappy and fast as users interact with it? Or does it slow down at times?
Angular user *ngFor structural directive to loop over data and manipulate the DOM by adding and removing DOM elements. However, if not used well, it may damage your app’s performance. Let's say we have a large object containing User data and we need to iterate over this object and display the data on UI.
I have encountered the somewhat infamous ng-repeat performance issue. I have a table with about 10 columns which consists of a row for each day. If I try:
<tr ng-repeat="row in rows">
<td ng-repeat="column in columns">
{{ row[column.id] }}
</td>
</tr>
I run into performance issues after creating on the order of 100-200 days.
But the truth is, there are a ton of stupid things about this approach. For one, no display can show this many rows. Why add a bunch of crap to the screen that isn't going to be rendered? Also, as others have made apparent, it's unlikely that a user can meaningfully interact with enough items on a page to warrant 2k bindings.
I was going to go with some complicated pre-rendering of rows or even the whole table that would compile all of the html and then update every time there was a change to the table data. But then I had some little widgets in the rows that I wanted to have bindings on.
So instead, I went with http://binarymuse.github.io/ngInfiniteScroll/ It makes it super easy to add or remove items on the fly from your page. Now I can show 40ish rows at any time, and when the user scrolls in either direction it will append the new rows and get rid of the old. I had to do some modifications to implement the remove elements part, but for me it's by far the best option because it allows me to stick with the angularjs mentality which I really like and still get good performance.
It seems to me that your issue can be fairly trivially solved with an ng-if instead of ng-show. If you remove the elements from the DOM, there shouldn't be any more issue with bindings for that item.
Should be easy enough to test with what you have and some extra ng-repeats if necessary though right? It's super easy to plug in infinite-scroll to give it a whirl.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With