0

I found questions similar to this , but most of them ended up being about ng-repeat or something similar, which is not what I am after here.

In my case I am trying to loop through an array of messages to display one message at a time in the view. Here is my view:

<div id="centerWrap" ng-init="looptyloop()">
<p>{{centerWrapMessage[loop.loop]}}</p>
</div>

My controller has both $scope.centerWrapMessage and $scope.loop.

My controller is here:

$scope.centerWrapMessage = ["Click your category and then click your bread for more information.","If you intend to ship your order, please select a gift box","To add an item to your cart, hit the cart button"],
    $scope.loop = {
        loop: 0
    },
    $scope.looptyloop = function() {

    var i = 0;                    
function myLoop () {           
   setTimeout(function () {   
     i++; 
     $scope.loop.loop = i;
     if (i == $scope.centerWrapMessage.length - 1){
     i = -1;
     }
      if (i < $scope.centerWrapMessage.length) {            
         myLoop();             
      }                        
   }, 2222)
}

myLoop();        

},  

I can see in the console log (when I put it in) that the $scope.loop.loop is looping through like I want, but it never changes in the view. Why is this?

Thank you!

2 Answers 2

3

As your myLoop function is outside angular world so whenever you changes $scope object from outside, you need to call digest cycle explicitly i.e. $scope.$apply does for you. Also there are alternatives to do the same like you can use $timeout or $scope.$applyAsync i.e. newly introduce in Angular 1.3.

Using $scope.$apply() or $scope.$applyAsync

function myLoop () {           
   setTimeout(function () {   
     i++; 
     $scope.$apply(function() { // Or use $scope.$applyAsync (Preferred)
        $scope.loop.loop = i;
     });
     if (i == $scope.centerWrapMessage.length - 1){
     i = -1;
     }
      if (i < $scope.centerWrapMessage.length) {            
         myLoop();             
      }                        
   }, 2222)
}

Using $timeout

function myLoop () {           
    $timeout(function () {   
      i++; 
      $scope.loop.loop = i;
      if (i == $scope.centerWrapMessage.length - 1){
         i = -1;
      }
      if (i < $scope.centerWrapMessage.length) {            
          myLoop();             
      }                        
  }, 2222)
}

Make sure you've injected $timeout service in your controller.

Sign up to request clarification or add additional context in comments.

4 Comments

Can you explain why this is necessary?
Because angular will not be aware of what happened in timeout. Instead you can use $timeout which will trigger digest for you.
Yes, $timeout will also work or else use $scope.$apply. Both will work.
You could also use $scope.$applyAsync(function(){}) in order to not get an error if the $digest cycle is already running
0

Check out this plunker.

var app = angular.module('plunker', []);

app.controller('MainCtrl', ['$scope', '$timeout', function($scope, $timeout) {
  $scope.centerWrapMessage = [
    "Click your category and then click your bread for more information.",
    "If you intend to ship your order, please select a gift box",
    "To add an item to your cart, hit the cart button"
  ];

  $scope.item = 'World';

  var i = 0;
  $scope.item = $scope.centerWrapMessage[i];

  function myLoop () {
    i++;
    $timeout(function() {
      console.log(i, $scope.centerWrapMessage[i]);
      $scope.item = $scope.centerWrapMessage[i];
    }, 0);

    if (i === $scope.centerWrapMessage.length - 1){
      i = 0;
    }
    $timeout(myLoop, 750);
  }

  myLoop();        

}]);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.