Combating AngularJS executing controller twice
I understand AngularJS runs through some code twice, sometimes even more, like $watch
events, constantly checking model states etc.
However my code:
function MyController($scope, User, local) {
var $scope.User = local.get(); // Get locally save user data
User.get({ id: $scope.User._id.$oid }, function(user) {
$scope.User = new User(user);
local.save($scope.User);
});
//...
Is executed twice, inserting 2 records into my DB. I'm clearly still learning as I've been banging my head against this for ages!
The app router specified navigation to MyController
like so:
$routeProvider.when('/',
{ templateUrl: 'pages/home.html',
controller: MyController });
But I also had this in home.html
:
<div data-ng-controller="MyController">
This digested the controller twice. Removing the data-ng-controller
attribute from the HTML resolved the issue. Alternatively, the controller:
property could have been removed from the routing directive.
This problem also appears when using tabbed navigation. For example, app.js
might contain:
.state('tab.reports', {
url: '/reports',
views: {
'tab-reports': {
templateUrl: 'templates/tab-reports.html',
controller: 'ReportsCtrl'
}
}
})
The corresponding reports tab HTML might resemble:
<ion-view view-title="Reports">
<ion-content ng-controller="ReportsCtrl">
This will also result in running the controller twice.
AngularJS docs - ngController
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.
When you use ngRoute with the ng-view
directive, the controller gets attached to that dom element by default (or ui-view if you use ui-router). So you will not need to attach it again in the template.
I just went through this, but the issue was different from the accepted answer. I'm really leaving this here for my future self, to include the steps I went through to fix it.
- Remove redundant controller declarations
- Check trailing slashes in routes
- Check for
ng-ifs
- Check for any unnecessary wrapping
ng-view
calls (I accidentally had left in anng-view
that was wrapping my actualng-view
. This resulted in three calls to my controllers.) - If you are on Rails, you should remove the
turbolinks
gem from yourapplication.js
file. I wasted a whole day to discover that. Found answer here. - Initializing the app twice with ng-app and with bootstrap. Combating AngularJS executing controller twice
- When using $compile on whole element in 'link'-function of directive that also has its own controller defined and uses callbacks of this controller in template via ng-click etc. Found answer here.