user3107057
user3107057

Reputation: 31

Angular Directive are Loading Multiple time

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

Answers (3)

adamjld
adamjld

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

user3107057
user3107057

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

Kevin
Kevin

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

Related Questions