Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular ng-repeat causes flickering

I'm displaying a list of thumbnails with this code:

<div class ="channel" ng-repeat ="channel in UIModel.channels" ng-class ="{evenchannel: ($index % 2) == 0, oddchannel: ($index % 2) == 1}">
            <img class="channel-img" ng-src ="data/channels/{{$index + 1}}/thumb"/>
</div>

In the controller I have an ajax request which grabs new thumbnail images. Angular thus updates the images but causes flickering. Is there a way to double buffer or not have the list deleted in the process of updating the DOM?

like image 830
tyuo9980 Avatar asked Jun 10 '14 15:06

tyuo9980


3 Answers

To go along with @cexbrayat's answer, if you don't have any IDs you can also just associated it and track by $index. Which is an internal iteration # during an ng-repeat.

<div ng-repeat="channel in UIModel.channels track by $index"></div> 
like image 121
Mark Pieszak - Trilon.io Avatar answered Sep 27 '22 21:09

Mark Pieszak - Trilon.io


You can use track by in your ng-repeat with a unique identifier. If I suppose your channel object has an id, you can do :

<div class ="channel" ng-repeat="channel in UIModel.channels track by channel.id"></div>

The tracking avoids the complete DOM deletion and recreation at every updates, as Angular will be able to track if the element is the same as previously and will keep the DOM element.

like image 40
cexbrayat Avatar answered Sep 27 '22 19:09

cexbrayat


Try the answers from @Mark Pieszak and @cexbrayat first, however if you are using ngAnimate in your application, they may not completely solve your problem.

In addition to:

<div class="channel" ng-repeat="channel in UIModel.channels track by channel.id"></div>

I needed to add the following CSS to disable animation for this ng-repeat:

.channel .ng-leave, .channel .ng-leave-active {
    display: none !important;
}

.channel .ng-move, .channel .ng-move-active {
    display: none !important;
}

This ensures that once the animation starts, the item is immediately hidden. The alternatives are to actually use an animation, or to disable the animation on the element in code with $animate.enabled('div.channel', false);.

like image 41
sflogen Avatar answered Sep 27 '22 19:09

sflogen