Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent AngularJs content flash on $scope update

When I update my $scope like so in a controller

$scope.item = "Hello";

Then the whole DOM for item seems to be removed and then added again. This seems fine, but if I have a list of items and do

$scope.items = Resource.query(); 

To update all the items then all of the DOM for items is removed and then re-added, this looks a broken and clumsy - is there anyway around this removing and then adding of the DOM elements when $scope is updated?

This issue is further exasperated if $scope.items and its children are used inside several ng-repeat statements as all of those ng-repeat sections are removed and then re-added.

EDIT

I have read this and feel that this is the issue https://www.binpress.com/tutorial/speeding-up-angular-js-with-simple-optimizations/135

That I have so much "stuff" going on the $digest is just slow. I am working on an example but in the mean time imagine this try of data

{
    {
        id: 1, 
        name: "name1", 
        something: {
            id: 10,
            name: "something10"
            else: {
                id: 15,
                name: "else15"
            }
        }
    }
}

But there are 20 such objects all with nested objects - this appears to be the issue. That there are so many objects being parsed and bound to the DOM that the $watchers are just taking a long time to go over everything.

EDIT 2

I made this demo, perhaps I am using resource wrong? http://plnkr.co/edit/QOickL0Dyi8jmuvG9mzN

But the items are replaced every 5 seconds, on replace they all disappear and then reappear. This is the issue I am having.

like image 952
Jake N Avatar asked Jan 08 '23 12:01

Jake N


1 Answers

This is a common problem when using ng-repeat. In order to track the objects the directive itself by default adds additional property to every object in the array ($$hashkey). And whenever new object is added or removed from the array the same is happening for it's associating DOM element. When the array is replaced with new array (ex. returned from the server) as you mentioned all the DOM elements representing objects from the previous array are removed and replaced with new DOM elements for the new objects. This is simply because the new objects in the array does not have the $$hashkey property even though they may be semantically the same.

A solution for this common problem came in Angular 1.2 version with the track by clause. You can find more detailed explanation about it in this post.

In your case the objects in the array have an 'id' property which it's a good candidate for tracking them if you can guarantee it's uniqueness. So using ng-repeat like this will improve it's performance.

<div ng-repeat="item in items track by item.id">
  <!-- tpl -->
</div>
like image 108
S.Klechkovski Avatar answered Jan 21 '23 07:01

S.Klechkovski