I\'ve got an angular app like:
angular.module(\'ngStyleApp\', [])
.controller(\'testCtrl\', function($scope) {
$scope.list = [1,2,3];
$scope.getStyles
The Angular $digest
cycle evaluates the ngStyle attribute at least twice - once to get the value and once to check if it has changed. It actually keeps iterating until the value settles so could potentially check the value many times.
Here's a picture to illustrate this:
Here is a good blog post illustrating this: angular digest blog
Actually, try this quote from StackOverflow that says it very well:
When watched functions are evaluated (during $digest) if any of them have changed from the previous $digest then Angular knows that change might ripple through to other watched functions (perhaps the changed variable is used in another watched function). So every watch is re-evaluated (also called dirty processing) until none of the watches results in a change. Thus typically you'll see 2 calls to watched functions per digest and sometimes more (up to 10- at 10 loops through it gives up and reports an error saying it can't stabilize).
(Reference here)
This is the code of the ngStyle
directive:
var ngStyleDirective = ngDirective(function(scope, element, attr) {
scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {
if (oldStyles && (newStyles !== oldStyles)) {
forEach(oldStyles, function(val, style) { element.css(style, '');});
}
if (newStyles) element.css(newStyles);
}, true);
});
Notice that there is a scope.$watch
for attr.ngStyle
, that watch is what is making it trigger twice.
For instance, if you try to do the same thing using ngInit
, you will notice that the function only gets called once. Now, lets have a look at the code of the ngInit
directive, it looks like this:
var ngInitDirective = ngDirective({
priority: 450,
compile: function() {
return {
pre: function(scope, element, attrs) {
scope.$eval(attrs.ngInit);
}
};
}
});
Notice that there is no watch
in this directive.