Reputation: 31
Is this a bug in Angular or am I missing something:
Calling a function from the directive's template shows that that function is executed 11 times ! with a templateurl, and 22 times !! with a string template.
angular.module('testDirective', [])
.directive('myDirective', function() {
return {
scope:{},
template: '{{increment()}} {{count}}',
controller: function($scope) {
$scope.count = 0;
$scope.increment = function() {
$scope.count += 1;
};
}
};
})
HTML:
<body ng-app="testDirective">
<my-directive></my-directive>
</body>
RESULT:
22
Here is a Plunker with both template and templateUrl methods.
This is quite an issue when method calls are involved within repeaters as an example, this ends up calling the same method dramatically more time than it should.
Anybody could shed some light on this ?
Upvotes: 2
Views: 2812
Reputation: 310
increment()
is being called every time the view is being updated. On load, increment()
is called, and the count goes up by 1 which causes the view to be updated and increment()
to be called again.
If you look in your console, you will see that Angular is telling you that it's stuck in an infinite $digest loop
.
Upvotes: 0
Reputation: 31
I also found this post which relates to the same issue to be useful : Using ng-class with a function call - called multiple times
Also one-time binding can be a solution is some case as related here : Angular lazy one-time binding for expressions
Upvotes: 1
Reputation: 6014
{{increment()}}
in your view is going to be called every time the digest cycle is called, like any bound expression would be. If you were incrementing in the controller function itself, rather than a bound function called from the view template, that would indicate that the directive was "loading" multiple times. But the nature of Angular is that any bound expression is going to be checked for changes repeatedly during the digest cycle, and anything you expect to happen only once (or even a predictable number of times) should never happen inside an expression bound to a content element. On the other hand, expressions bound to event handlers only execute when the event fires.
The model takes some time to get used to. Though the old documentation argued against it, you can use functions in content binding expressions, but they should never change state. You have no real control over when $digest() is called, and if you're thinking in the Angular way, you won't want to.
Upvotes: 6