Reputation: 6543
i'm trying to figure out how Angular works and am having trouble getting my view to update when the model changes..
HTML
<div ng-app="test">
<p ng-controller="TestCtrl">
{{testValue}}
</p>
</div>
JS
var app = angular.module('test', []);
app.controller('TestCtrl', function ($scope) {
$scope.testValue = 0;
setInterval(function() {
console.log($scope.testValue++);
}, 500);
});
any ideas?
Upvotes: 78
Views: 109706
Reputation: 81
Do not use $scope.$apply()
angular already uses it and it can result in this error
$rootScope:inprog Action Already In Progress
if you use twice, use $timeout
or interval
Upvotes: 8
Reputation: 1149
Just use $interval
Here is your code modified. http://plnkr.co/edit/m7psQ5rwx4w1yAwAFdyr?p=preview
var app = angular.module('test', []);
app.controller('TestCtrl', function ($scope, $interval) {
$scope.testValue = 0;
$interval(function() {
$scope.testValue++;
}, 500);
});
Upvotes: 37
Reputation: 4254
As Ajay beniwal mentioned above you need to use Apply to start digestion.
var app = angular.module('test', []);
app.controller('TestCtrl', function ($scope) {
$scope.testValue = 0;
setInterval(function() {
console.log($scope.testValue++);
$scope.$apply()
}, 500);
});
Upvotes: 126
Reputation: 67326
setTimout
executes outside of angular. You need to use $timeout
service for this to work:
var app = angular.module('test', []);
app.controller('TestCtrl', function ($scope, $timeout) {
$scope.testValue = 0;
$timeout(function() {
console.log($scope.testValue++);
}, 500);
});
The reason is that two-way binding in angular uses dirty checking. This is a good article to read about angular's dirty checking. $scope.$apply()
kicks off a $digest
cycle. This will apply the binding. $timeout
handles the $apply
for you so it is the recommended service to use when using timeouts.
Essentially, binding happens during the $digest
cycle (if the value is seen to be different).
Upvotes: 30