TL;DR: Don’t declare your AngularJS controllers in both the router setup (with the controller property) and the view HTML (using ng-controller=) as it will lead to Angular triggering your controller multiple times.
When you’re an eager-beaver like me and coding like a maniac sometimes you’ll overlook the obvious. This was one of those cases for me.
Read more on the specifics of this issue after the break
I was saving the selection of an item in a subview and wanted to apply properties of the chosen data to my parent view.
The parent was loading and retrieving the chosen data object but quickly reloaded with the selection being set to null.
As it appeared, my parent controller was being loaded twice and I couldn’t figure out why until I found a viable explanation in an answer on ye allmighty StackOverflow. It clarifies that defining your view’s controller in both the router and the view html is overkill and will get your controller being initialized multiple times.
Checking out Angular’s own documentation for the ngController object made my comprehension even clearer, as it states:
MVC components in angular:
- Model — Models are the properties of a scope; scopes are attached to the DOM where scope properties are accessed through bindings.
- View — The template (HTML with data bindings) that is rendered into the View.
- Controller — The
ngControllerdirective specifies a Controller class; the class contains business logic behind the application to decorate the scope with functions and values
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-controllerin the template itself. This will cause the controller to be attached and executed twice.
To be complete, here are the two ways of defining a controller for a view. Let’s call the controller MyController for the sake of it:
Router definition for controller
[crayon-600995510a64c848270478/] View definition for controller* :
[crayon-600995510a658009165219/] *:in my case, I use ng-include to build my HTML structure using a view partial .html
And there you go: decide for yourself if you want to remove the definition in the router or remove the ng-controller statement from your view. I chose the first because I need the controller definition in my view to use the “MyController as mc” definition to get access to mc.property and mc.function().