When I click on a tab, the corresponding controller gets executed 4 times. Whys that?
E.g. DetailsPersonController
's init
function is executed 4 times. Should only be exectuted once the tab's view gets loaded.
Html Tabs:
<tabset>
<tab ng-repeat="tab in vm.tabs()"
heading="{{ tab.text | translate }}"
ui-sref="p.search.details.{{ tab.id }}"
active="tab.active">
<div ui-view="tabContent"></div>
</tab>
</tabset>
States:
.state( "p.search.details", {
url: "/details",
abstract: true,
templateUrl: "app/modules/partials/p/search/details/details.html",
controller: "DetailsController",
controllerAs: "vm"
} )
.state( "p.search.details.person", {
url: "/person",
views: {
"tabContent": {
templateUrl: "app/modules/partials/p/search/details/person/person.html",
controller: "DetailsPersonController",
controllerAs: "vm"
}
}
} )
.state( "p.search.details.details", {
url: "/details",
views: {
"tabContent": {
templateUrl: "app/modules/partials/p/search/details/details/details.html",
controller: "DetailsDetailsController",
controllerAs: "vm"
}
}
} )
.state( "p.search.details.driver", {
url: "/driver",
views: {
"tabContent": {
templateUrl: "app/modules/partials/p/search/details/driver/driver.html",
controller: "DetailsDriverController",
controllerAs: "vm"
}
}
} )
.state( "p.search.details.tests", {
url: "/tests",
views: {
"tabContent": {
templateUrl: "app/modules/partials/p/search/details/tests/tests.html",
controller: "DetailsTestsController",
controllerAs: "vm"
}
}
} )
When I click on a tab, the corresponding controller gets executed 4 times. Whys that?
E.g. DetailsPersonController
's init
function is executed 4 times. Should only be exectuted once the tab's view gets loaded.
Html Tabs:
<tabset>
<tab ng-repeat="tab in vm.tabs()"
heading="{{ tab.text | translate }}"
ui-sref="p.search.details.{{ tab.id }}"
active="tab.active">
<div ui-view="tabContent"></div>
</tab>
</tabset>
States:
.state( "p.search.details", {
url: "/details",
abstract: true,
templateUrl: "app/modules/partials/p/search/details/details.html",
controller: "DetailsController",
controllerAs: "vm"
} )
.state( "p.search.details.person", {
url: "/person",
views: {
"tabContent": {
templateUrl: "app/modules/partials/p/search/details/person/person.html",
controller: "DetailsPersonController",
controllerAs: "vm"
}
}
} )
.state( "p.search.details.details", {
url: "/details",
views: {
"tabContent": {
templateUrl: "app/modules/partials/p/search/details/details/details.html",
controller: "DetailsDetailsController",
controllerAs: "vm"
}
}
} )
.state( "p.search.details.driver", {
url: "/driver",
views: {
"tabContent": {
templateUrl: "app/modules/partials/p/search/details/driver/driver.html",
controller: "DetailsDriverController",
controllerAs: "vm"
}
}
} )
.state( "p.search.details.tests", {
url: "/tests",
views: {
"tabContent": {
templateUrl: "app/modules/partials/p/search/details/tests/tests.html",
controller: "DetailsTestsController",
controllerAs: "vm"
}
}
} )
Share
Improve this question
edited Jul 8, 2015 at 14:20
Pankaj Parkar
136k23 gold badges240 silver badges303 bronze badges
asked Jun 3, 2015 at 11:53
ShlomoShlomo
3,9908 gold badges52 silver badges82 bronze badges
16
-
the reason might be you used
vm.tabs()
inng-repeat
, that is getting called 4 times on each digest cycle..try giving static array there & see what is happening? – Pankaj Parkar Commented Jun 3, 2015 at 11:58 - static array does not fix it, still called 4 times – Shlomo Commented Jun 3, 2015 at 12:02
-
the controller gets called the same number of tabs that are passed by
vm.tabs()
! Weird! Why? – Shlomo Commented Jun 3, 2015 at 12:32 - because of digest cycle, the number of time digest cycle gets called expression gets evaluated..see this fiddle jsfiddle/7MhLd/850 – Pankaj Parkar Commented Jun 3, 2015 at 12:46
- 1 Duuuuuudddeeee :D I was going crazy – Shlomo Commented Jun 3, 2015 at 14:00
3 Answers
Reset to default 7You have ui-view
in wrong place, which was asking for tab using vm.tabs()
.
As there are 4 tags because of ng-repeat
rendered div 4 times because it has placed in tab
element which are going to repeat using ng-repeat
.
As ui-view
directive renders on page 4 times, that check the browser url and ask for that particular which has 4 tabs
that why all the controller with template got called 4 times inside your app.
Markup
<tabset>
<tab ng-repeat="tab in vm.tabs()"
heading="{{ tab.text | translate }}"
ui-sref="p.search.details.{{ tab.id }}"
active="tab.active">
</tab>
</tabset>
<div ui-view="tabContent"></div>
The solution is, take care where to place your ui-view
. It must not be within <tab>
<tabset>
<tab ng-repeat="tab in vm.tabs"
heading="{{ tab.text | translate }}"
ui-sref="p.search.details.{{ tab.id }}"
active="tab.active">
</tab>
</tabset>
<div ui-view></div>
I made it using this example and modifying it: http://plnkr.co/edit/efnfjoQ8Hft6AZITCR67?p=preview
.state('DocumentoMasterView', {
url: "/route2",
templateUrl: "route2.html",
controller:'myAppController'
})
.state('DocumentoMasterView.A', {
url: '/detail',
templateUrl: 'route2.A.view.html',
controller:'myAppControllerA'
})
.state('DocumentoMasterView.B', {
url: '/image',
templateUrl: 'route2.B.view.html',
controller:'myAppControllerB'
})
And:
$scope.go = function(route){
$state.go(route);
};
$scope.active = function(route){
return $state.is(route);
};
$scope.$on('$stateChangeSuccess', function() {
console.log($state);
$scope.tabs.forEach(function(tab) {
tab.active = $scope.active(tab.route);
});
});
Just to plete the already suggested solution, moving the ui-view outside tab can create css issues (it did in my case), so the solution is to keep ui-view inside tab and add ng-if ui-view div so that in the result, the html contains only one ui-view div.
N.B. : ng-if cannot be replaced by ng-show/ng-hide.