I konw that $apply
used to connect the Javascript context and the AngularJS context.
A simple example is below:
template:
<div>{{someVal}}</div>
javascript in controller:
setTimeout(function() {
scope.$apply(function(){scope.someVal = 123});
}, 1000);
We need use $apply
in above situation.
First Qustion:
If I modify javascript above to:
setTimeout(function() {
scope.someVal = 123;
}, 1000);
scope.$watch('someVal', function(val) {
console.info(someVal);
});
No console about someVal modified to 123... Why? Can't we watch expression modified in timeout callback?
Second Question:
If we use ngSwitch directive like below:
<div ng-switch on="sub">
<div ng-switch-when="a">
//state a
</div>
<div ng-switch-when="b">
//state b
</div>
</div>
When I modify the sub
in controller:
scope.sub = 'a';
setTimeout(function() {
scope.sub = 'b';
}, 1000);
No need to use $apply
!!!! Why?
I found that ngSwitch directive use $watch
to monitor on
attribute value. Why ngSwitch can watch scope attribute modified in timeout callback?????
Pls tell me the reason about the 2 qustions above.
You can use $timeout that is a wrapper for window.setTimeout and also this way you wont need to use $apply on the callback:
When you run code that is outside Angular, you'll need a way to let the Angular and the watchers of that value, to know that it has changed. Thats what $apply is for, it will allow watch listeners to fire
About you second question, of why the scope is updating without a $apply, you should be firing indirectly somehow a $apply/$digest. To give you a more specific answer, a Plunker will be necessary to check what else in going on on your code.
From AngularJs documentation
window.setTimeout is a JavaScript function, so whatever you use
setTimeout
you must use $apply() to update the model.Your second example wouldn't work without
$apply()
, I've made a demo to clarify the$watch
and$apply
issue. Please check it.Use the Angularjs $timeout service instead of setTimeout and you will not require $apply. Same thing is if you are using a jquery http call, use the angular http service to avoid using $apply.