Why is the ng-style function applied twice?

I have an angular application, for example:

angular.module('ngStyleApp', []) .controller('testCtrl', function($scope) { $scope.list = [1,2,3]; $scope.getStyles = function(index) { console.log('getting styles for index ' + index); return { color: 'red' }; }; }); 

with appropriate markup:

 <div ng-app="ngStyleApp"> <ul ng-controller="testCtrl"> <li ng-repeat="value in list" ng-style="getStyles($index)"> {{value}} </li> </ul> </div> 

The visible output consists of three red list items, as expected. But the operator writes to the console a total of 6 times, implying that the view is displayed twice:

 getting styles for index 0 getting styles for index 1 getting styles for index 2 getting styles for index 0 getting styles for index 1 getting styles for index 2 

Why?

+5
source share
2 answers

The Angular $digest loop evaluates the ngStyle attribute at least twice — once to get the value, and once to see if it has changed. It actually continues the iteration until the value is set, so it would be possible to repeatedly check the value.

Here is an image to illustrate this:

enter image description here

Here is a good blog post illustrating this: angular digest blog

Actually, try this quote from StackOverflow, which says it very well:

When observable functions are evaluated (during $ digest), if any of them has changed from the previous $ digest, then Angular knows that the change may pulsate to other observable functions (perhaps the changed variable is used in another observable function), so each watch reevaluated (also called dirty processing) until none of the hours leads to a change. Thus, as a rule, you will see 2 calls of the observed functions for the digest, and sometimes more (up to 10 - after 10 cycles it is reset through it and reports an error saying that it cannot stabilize).

(Link here )

+6
source

This is the ngStyle directive ngStyle :

 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); }); 

Note that there is scope.$watch for attr.ngStyle , which is what causes it to run twice.

For example, if you try to do the same with ngInit , you will notice that the function is only called once. Now let's look at the ngInit directive ngInit , it looks like this:

 var ngInitDirective = ngDirective({ priority: 450, compile: function() { return { pre: function(scope, element, attrs) { scope.$eval(attrs.ngInit); } }; } }); 

Please note that there is no watch in this directive.

+1
source

Source: https://habr.com/ru/post/1202931/


All Articles