2

In my angularjs app ,i have angular-ui-bootstrap tabs and on selection of tabs i change to different state using $state.go and with state transistion url on browser changes.

I have parent static tab pointing to $state:home.summary and dynamic tabs point to $state:home.summary.detail. When i go from parent to child, child resolve method is fired but when i move from child to parent,parent resolve doesn't fire

State changes,url changes but parent resolve is not fired and stays where it is.

Routes.js

 .state('home', {
          abstract: true,            
          url: '/home',
          templateUrl: 'scripts/home.html'
   })
.state('home.summary', {
url: '/summary', 
controller: 'SummaryCtrl',                
views: {               
       'summary': 
          {
                    templateUrl: "scripts/home/summary.html",
                    resolve: {
                     load: function ($rootScope,$stateParams,ServiceA) {
                        ServiceA.get().$promise;
                     }
                    }
          }
       }
})
.state('home.summary.detail', {
url: '/detail/:id',
controller:'DetailCtrl',                 
views: {               
       'detail': 
          {
                   templateUrl: "scripts/home/detail.html",
                   resolve: {
                     load: function ($rootScope,$stateParams,ServiceB,$timeout) {
                       var promise=ServiceB.retrieve(id);
                       return promise;
                     }
                    }
          }
       }
}) 

Tabs.html

  <div ng-controller="TabsCtrl">
  <ul tabset>
  <li tab select="selectStaticTab()">
   <span tab-heading>Search<a style="left:9px" class="glyphicon glyphicon-search"></a>         </span>       
         <div class="well">  
             <div ui-view="summary"></div>    
         </div> 
   </li>
    <li tab ng-repeat="tab in tabs track by tab.id"  active="tab.active"     select="tab.select()"> 
     <span tab-heading>{{tab.title}}</span>
         <div ui-view="detail"></div>
   </li>
  </ul>   
  </div>

why parent resolve is not fired from child state??? Any help will be appreciated.

Thank you

enter image description here

svp
  • 495
  • 1
  • 12
  • 26

1 Answers1

0

There are many issues with your draft, I tried to make them all working here

1) Firstly, we are using the ui-router so we cannot use the <div ng-controller="TabsCtrl">. We do have states now, and each state can have more views, which DO have their own controllrs (i.e. controller belongs to view beeing part of a state)

2) As just explained, views do have controller (exactly one). Not states - they do NOT have controllers. So I moved the controller definition from state, into view...

    .state('home.summary', {
      url: '/summary',
      // NOT HERE
      views: {
        'summary': {
          ...
          controller: 'SummaryCtrl',
        }
      }
    })
    .state('home.summary.detail', {
      url: '/detail/:id',
      // NOT HERE
      views: {
        'detail@home': {
          ...
          controller: 'DetailCtrl',

3) resolve of the parent and child should have different names. I changed the child resolve like this (see mainyl the name load2 instead of load):

    .state('home.summary.detail', {
      url: '/detail/:id',          
      views: {
        'detail@home': {
          ...
          resolve: {
            load2: function($rootScope, $stateParams) {
              return 'loaded child with param ' + $stateParams.id ;
            }
          },
        }

4) Even if we want to have that: ui-view cannot be inside of the repeater. Well it can, but it would simply mean that the state view would be placed there as many times as repeated (but see the links below .. how to do that)

I moved thes ui-view outside of the repeater:

<li tab 
  ng-repeat="tab in tabs track by tab.id" active="tab.active" select="tab.select()">
  <span tab-heading>{{tab.title}}</span>
</li>
<hr />
<div ui-view="detail"></div> // moved outside of repeater

5) if we target the view, which is not placed directly in its parent, we have to use absolute naming, that's why I used this:

    .state('home.summary', {
      url: '/summary',          
      views: {
        'summary': { // ok name, while direct parent is home
         ....
        }
      }
    })
    .state('home.summary.detail', {
      url: '/detail/:id',          
      views: {
        'detail@home': { // we have to add @home to say that the target  
          ....           // is in a home state not in our parent
        }
      }

Check the complete working solution here

Few very interseting reading (I'd say):

Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • Thank you and thats good explanation.I discovered parent resolve is not fired gain from child because parent state has already resloved and loaded and i am not sure it is good to reload parent again,if so how to reload parent again???if parent is reloaded will the child state template loses the the previous resolved data??? – svp Jul 30 '14 at 06:20
  • Yes, parent reloaded === all resolvers will be run again. On the other hand if only child is relaoded, parent resolve is not called, it does already have the value ... important is different naming ;) good luck with ui-router Suggestion: Maybe thry to see it differently, please check this: http://stackoverflow.com/a/20558850/1679310 and also http://stackoverflow.com/a/23582847/1679310 - we should move resolve stuff to state which is the least common denominator... I'd say ;) – Radim Köhler Jul 30 '14 at 06:21