I'm new to AngularJS. I'm looking at using the $timeout
service. I've read that one of the reasons for using $timeout
over the JavaScript setTimeout
function is because changes to variables in the $scope
don't get updated in the UI until $scope.$apply
is called. While that's the word, I'm unable to confirm this with actual code. I've written the following:
index.html
<div ng-app="myApp">
<div ng-controller="myController">
<div>AngularJS Count: {{total1}}</div>
<br />
<div>setTimeout Count: {{total2}}</div>
<br />
<button ng-click="start()">start</button>
</div>
</div>
myController.js
var app = angular.module("myApp", []);
function myController($scope, $timeout) {
$scope.total1 = 0;
$scope.total2 = 0;
$scope.isStarted = false;
$scope.toggle = function() {
if (!$scope.isStarted) {
$scope.isStarted = true;
$timeout(ngUpdate, 1000);
setTimeout(jsUpdate, 1000);
}
};
function ngUpdate() {
$scope.total1 = $scope.total1 + 1;
}
function jsUpdate() {
$scope.total2 = $scope.total2 + 1;
}
}
In this code sample, the changes to the variables on the $scope
are updated in the UI. I'm trying to see a scenario, in code, where a change via the setTimeout
function doesn't update the UI until $scope.$apply
is called. Am I misunderstanding? Or was a change made to the AngularJS framework that makes the original assertion out-of-date.
Since, you are calling setTimeout
from inside $scope.toggle
, this code is already executing in the context of a $digest
cycle. So, there is no need to call $apply
.
$timeout
will test if it is in a $digest
and then only call $apply
if it needs to. This is very useful when building directives that bind to events that are happening outside of the angular context.
Here is a directive scenario when $timeout
is needed:
app.directive('myDirective', function() {
return {
link: function(scope, element) {
element.bind('click', function() {
// $timeout is needed here because the 'click' event is outside angular
}
}
}
});