0

What do I need to do to update the scope variable in the UI on every iteration of the loop in this example?

JS

var q = 100;
while ( q > 0 ) {
  $scope.someThing = q;
  q--;
}

HTML

{{someThing}}

I thought I was on to something with the following but it isn't working. All I see is the final result, not each iteration.

var q = 1000;
while ( q > 0 ) {
    $scope.$apply(function () {
      $scope.someThing = q;
      q--;
    });
}

--Edit--

Thanks for the suggestions on interval/timeout. I think I understand why this is needed now. But I was hoping I could "callback" the redraw somehow so the loop still runs as fast as possible. Is there a simple way to achieve that?

2
  • You would need to perform it in a $timeout basically you would need to make it async. loop runs synchronously. SO your loop completes running digest cycle happens and view gets updated with the result. Commented Jan 2, 2015 at 16:51
  • 2
    That loop executes extremely fast - you won't see it count up. Commented Jan 2, 2015 at 16:51

3 Answers 3

3

That loop executes extremely fast - you won't see it count up. Thanks to @PSL for a better explanation: Basically JavaScript loop runs synchronously. And Angular depends upon the digest cycle to update the view based on the scope property. In this case loop runs and then digest cycle happens. You would instead need to let the digest cycle happen after every count in order to see progressive update.

Use a $timeout if you want it to work:

var q = 100;

function subtractQ() {
    q--;
    $scope.someThing = q;
}

$timeout(subtractQ, 1000);

Or $interval

$interval(function() {
    q--;
    $scope.someThing = q;
}, 1000);
Sign up to request clarification or add additional context in comments.

7 Comments

It really not just about it running extremely fast. Basically javascipt loop is synchronous. And angular depends upon the digest cycle to update the view based on the scope property. In this case loop runs and then digest cycle happens.
So is there has to be some sort of delay in order for it to be redrawn on the UI? That seems like it would slow things down unnecessarily. Can't I "callback" the redraw somehow so it runs as fast as possible?
@PSL -- Much better explanation - added it to my answer.
@xdaxdb -- What is your overall goal - I thought it was to have a countdown the user could see, is there a different purpose?
In my actual application I am trying to write, there is a mathematical/statistical experiment running in a loop. I want to display the results as they happen. I want it to run as fast as possible while also making the results change rapidly on the page.
|
1

It's because you need to do it async with a timeout between each iteration. I'd use $interval for this:

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

testApp.controller('testCtrl', ['$scope', '$interval', function($scope, $interval) {

  var q = 100;
  var interval = $interval(decreaseQ, 50);
  
  function decreaseQ() {
    $scope.someThing = q;
    
    if(q == 0) $interval.cancel(interval);
    else q--;
  }
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="testApp" ng-controller="testCtrl">
  {{someThing}}
</div>

1 Comment

Great answer, it's hard to choose which answer to mark correct when there are multiple answers that are similar.
1

You could try $timeout instead of the while loop to delay the function.

Something like this:

 $timeout(function(){
    $scope.something = q;
    q--;
  }, 1000);

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.