migdsb
migdsb

Reputation: 705

Controller function called multiple times

I was attempting to get AngularJs to apply an active class on a nav section depending upon the active route. My solution works fine but I noticed a curious behaviour -- more on that below. For now, here's how the active class is set in the HTML:

<ul class="menu" ng-controller="ControllerHeader">
  <li><a ng-class="{ active: isActive('/foo') }" href="#/foo">foo</a></li>
  <li><a ng-class="{ active: isActive('/bar') }" href="#/bar">bar</a></li>
  <li><a ng-class="{ active: isActive('/baz') }" href="#/baz">baz</a></li>
</ul>

ControllerHeader and isActive are defined as given:

var app = angular.module('app', [ ]);

app.controller( 'ControllerHeader', ['$scope', '$location',
  function ($scope, $location) {
    $scope.isActive = function (location) {
      // multiple logging occurs: exactly 3*3 times
      console.log(location, $location.path());
      return location === $location.path();
    };
  }
] );

The issue I've noticed is that isActive above is called 3 * 3 times! Could someone please explain why? How can I fix it that such that it is called once per item only?

Upvotes: 0

Views: 5008

Answers (2)

floribon
floribon

Reputation: 19193

If you are using Angular 1.3+, you can use the :: operator to only evaluate the expression once:

<ul class="menu" ng-controller="ControllerHeader">
  <li><a ng-class="::{ active: isActive('/foo') }" href="#/foo">foo</a></li>
  <li><a ng-class="::{ active: isActive('/bar') }" href="#/bar">bar</a></li>
  <li><a ng-class="::{ active: isActive('/baz') }" href="#/baz">baz</a></li>
</ul>

If you are using an older version of Angular, you can use a third party library such as bindonce

As for why this is happening without binding once, indeed it is covered by many other questions. If you want the class to be dynamically set depending on angular context, Angular need to execute the function to check its value. That is called executing the watchers during a digest cycle, and this is done often.

Upvotes: 4

squiroid
squiroid

Reputation: 14027

All expression that you use in AngularJS get evaluated multiple times when a digest cycle runs. This is done for dirty checking which validates whether the current value of expression is different from the last value.

Upvotes: 0

Related Questions