AngularJS: $ rootScope: infdig error when calling ng-style function inside ng-repeat

I am trying to create animation on some phrases that will be displayed on the main page of the site, in an arbitrary position and with fading and broadcast effects.

I would achieve this by using the ng-style attribute inside the ng-repeat attribute and setting the ng-style value to call the JavaScript function defined inside the HomeController.

Using this reason, angular is called to throw an exception: $ rootScope: error infdig 10 $ digest () iterations. Aborting! Observers fired in the last 5 iterations

I read so much about this, but not a single solution resolved my case. Can anybody help me?

Here is the part of index.html:

<div class="phrasesContainer" animate-phrases=""> <h3 class="flying-text" ng-repeat="phrase in Phrases" ng-style="getTopLeftPosition()">{{phrase}}</h3> </div> 

Here is the controller function:

 $scope.getTopLeftPosition = function() { var top = randomBetween(10, 90); var left = getRandomTwoRange(5, 30, 70, 80); return { top: top + '%', left: left + '%' }; 

}

Here is a demo: http://plnkr.co/edit/8sYks589agtLbZCGJ08B?p=preview

+8
javascript jquery angularjs angularjs-rootscope ng-style
source share
4 answers

Here's a solution in which I have moved your generation of style into a directive. The position is set right before the item is displayed. Since this is a CSS change, I also modified the style so that the position does not move.

Here is the directive. The code I excluded was not changed:

 app.directive('animatePhrases', function() { return { restrict: 'A', link: function(scope, element, attrs) { setTimeout(function() { ... }, 1000); function changeText() { var currentActive = $('.phrasesContainer .active'); var nextActive = currentActive.next(); currentActive.toggleClass('active'); if (nextActive.length == 0) nextActive = $('.phrasesContainer .flying-text').first(); nextActive.css(getTopLeftPosition()); // Add this nextActive.toggleClass('active'); setTimeout(changeText, 5000); } function getTopLeftPosition() { ... } function getRandomTwoRange(firstStart, firstEnd, secondStart, secondEnd) { ... } function randomBetween(min, max) { ... } } }; }); 

CSS

 .flying-text { transition: opacity 2s ease-in-out, margin 2s ease-in-out; position: absolute; opacity: 0; font-size: 1.5em; } 

In your HTML, just remove ng-style .

Plunker: http://plnkr.co/edit/bZB3A5hD7Bc4r4pp1g7V?p=preview

+2
source share

@Hieu Le hinted at a problem, but your problem is that since you always return a random position in your getTopLeftPosition function, the digest java loop will be called every time to actually propagate observer changes. This made him continue to work again and again.

What you can do is pre-compute your random positions and then use them in your html.

For example, in your activation function, you can do something like this:

  function activate() { $scope.Phrases = ["Phrase 1", "Phrase 2", "Phrase 3", "Phrase 4", "Phrase 5", "Phrase 6"]; $scope.PhrasesAndPositions = $scope.Phrases.map(function(phrase){ return { phrase: phrase, position: getTopLeftPosition() } }); } 

And then you can change your html to something like this:

  <div class="phrasesContainer" animate-phrases=""> <h3 class="flying-text" ng-repeat="pap in PhrasesAndPositions" ng-style="pap.position">{{pap.phrase}}</h3> </div> 

Here is the work plan with my changes: http://plnkr.co/edit/FD9hYX9Q5wUkW2q7y86M?p=preview

+4
source share

that way you can control your ng-style

 $scope.getTopLeftPosition = function() { $scope.top = randomBetween(20, 90); $socpe.left = getRandomTwoRange(5, 30, 70, 80); } function getRandomTwoRange(firstStart, firstEnd, secondStart, secondEnd) { var isLower = (Math.random() * 2) < 1; if (isLower) return randomBetween(firstStart, firstEnd); else return randomBetween(secondStart, secondEnd); } function randomBetween(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } <body> <div ng-controller="HomeController"> <div class="row" style="height:100%"> <div class="phrasesContainer" animate-phrases=""> <h3 class="flying-text " ng-repeat="phrase in Phrases" ng-style="{ 'top' : top, 'left' : left }">{{phrase}}</h3> </div> </div> </div> 

0
source share

I think the problem is that you cannot bind ng-style. He believes that he should constantly call getTopLeftPosition.

I got my job here. Timing is a bit low, but there are no more errors. Here I used $ interval to repeat things:

Please view here: http://plnkr.co/edit/B4iMZXMvZFoYMCKNvVrc?p=preview

  $scope.phrase_style = getTopLeftPosition(); function change_phrase_style() { $scope.phrase_style = getTopLeftPosition(); } function start_interval() { change_phrase_style(); $interval(function(){ change_phrase_style(); }.bind(this), 5000); } setTimeout(start_interval, 1000); 

This could also be due to: angularjs $ digest infinite loop when area changes don't change

0
source share

All Articles