Random thoughts & observations

From the mundane to the profound and everything in between here’s what’s rocking our world

Resolving AngularJS executing controller twice issue

Posted: June 28, 2015
Written by: Saints At Play
Category: AngularJS

If you've been developing with AngularJS for some time then you may have unwittingly come across the following issue: your controller is executed twice.

Seems like one of those coding problems that shouldn't exist but fixing this is, thankfully, quite simple...

AngularJS controllers

AngularJS attaches controllers to the DOM in one of 3 ways:

Routing and redeclaring the controller

Let's say, for example, you have declared controllers within your application using AngularUI state definitions such as the following:

$stateProvider
 .state('index',
 {
   url          :   '/',
   templateUrl  :   'templates/home.html',
   controller   :   'HomeController'
 })

And then, in the home.html view template, you also declare the controller using the ng-controller directive like so:

 <div ng-controller="HomeController">

Then you have, without realising it, attached the controller twice (once through the state definition and twice through the ng-controller directive) which causes the code contained within the controller to execute twice as well.

Here's what the official Angular JS docs have to say on the matter:

Note that you can also attach controllers to the DOM by declaring it in a route 
definition via the $route service. 

A common mistake is to declare the controller again using ng-controller in the template 
itself. This will cause the controller to be attached and executed twice.

The simplest solution then is to remove the ng-controller directive from the HTML of the view that it is associated with and rely solely on the state definition (or route definition - depending on whether you choose to work with ngRoute or AngularUI routing) to declare the controller instead.

If the above scenario isn't applicable and you find your controller still being attached/executed twice then you might want to look at the following situations that can also cause this bug to happen:

Attaching controllers in custom directives

return {
  restrict: 'A',
  controller: 'HomeController',
  link: function ($scope) {

If you happen to have the HomeController attached to the template (using the ng-controller directive) in which the above directive is called then this too can cause the controller to be attached/executed twice.

Close your directives

If you call your custom directives within your app like so:

<my-custom-directive><my-custom-directive>

Then you might experience that controller logic being attached/executed twice as a result of the directive not being closed properly. It's definitely an edge case scenario but one that's worth investigating.

Wrapping it up

If you should find your controller logic being attached/executed twice use the following checklist to help you track down what might be causing this to happen:

  1. Remove ng-controller directives from view templates when using route/state definitions to attach those controllers
  2. Check your custom directives to see if controllers are being attached to view templates with those controllers already in existence
  3. Check your directives are closed properly when being embedded in the view template
  4. Finally, check to see if there are any conditional statements (using the ng-if directive) calling a view more than once that could trigger any controller attached to that view

Happy coding!

« Return to Posts

Comments

There are no comments

Posting comments after three months has been disabled.