5

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"
               }
            }
         } )
16
  • the reason might be you used vm.tabs() in ng-repeat, that is getting called 4 times on each digest cycle..try giving static array there & see what is happening? Commented Jun 3, 2015 at 11:58
  • static array does not fix it, still called 4 times Commented Jun 3, 2015 at 12:02
  • the controller gets called the same number of tabs that are passed by vm.tabs()! Weird! Why? 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.net/7MhLd/850 Commented Jun 3, 2015 at 12:46
  • 1
    Duuuuuudddeeee :D I was going crazy Commented Jun 3, 2015 at 14:00

3 Answers 3

7

You 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>
Sign up to request clarification or add additional context in comments.

Comments

3

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);
       });
   });

1 Comment

I couldn't help but notice that the content of the tab isn't actually shown inside the .tab-content element
0

Just to complete 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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.