1

Here is an example to check http://embed.plnkr.co/uVMlkk/preview

When we navigate to 'page2' route there is a 'hey, I'm a subroute' note. But once we navigate anywhere else that note will disappear forever.

The goal is to make some nested states to be shown right away (as a default ones).

I assume there should be some cases using $state.go(), but can't figure it out so far. Any help is highly appreciated.

State definition snippet:

  .state('root.page2.tab', {
    url: '/:tabId',
    templateUrl: 'tpl.page2.tab.html',
    controller: 'Page2TabController'
  })

  .state('root.page2.tab.subroute', {
    url: '',
    templateUrl: 'tpl.page2.tab.subroute.html'
  })

the content of the 'tpl.page2.tab.subroute.html':

hey, I'm a subroute

related controller:

  .controller('Page2TabController', ['$scope', '$state', function($scope, $state) {
    $scope.tabId = $state.params.tabId;
    $state.go('root.page2.tab.subroute');
  }])
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335

2 Answers2

2

There is a fixed version.

I removed the url from the 'root.page2.tab.subroute'

.state('root.page2.tab.subroute', {
    //url: '',
    templateUrl: 'tpl.page2.tab.subroute.html'
})

And because the parent has defined paramater tabId:

.state('root.page2.tab', {
    url: '/:tabId',
    templateUrl: 'tpl.page2.tab.html',
    controller: 'Page2TabController'
})

We have to pass that param inside of the redicrection:

.controller('Page2TabController', ['$scope', '$state', function($scope, $state) {
    $scope.tabId = $state.params.tabId;
    // instead of this
    // $state.go('root.page2.tab.subroute');
    // we need this
    $state.go('root.page2.tab.subroute', $state.params);
 }])

Check the working, fixed version here

ANOTHER approach - using redirectTo - there is a working plunker

One way, inspired by this:

Redirect a state to default substate with UI-Router in AngularJS

could be to add a very smart but small redirect code snippet:

.run(['$rootScope', '$state', function($rootScope, $state) {
    $rootScope.$on('$stateChangeStart', function(evt, to, params) {
      if (to.redirectTo) {
        evt.preventDefault();
        $state.go(to.redirectTo, params)
      }
    });
}])

And adjust our state like this:

.state('root.page2.tab', {
    url: '/:tabId',
    templateUrl: 'tpl.page2.tab.html',
    controller: 'Page2TabController',
    redirectTo: 'root.page2.tab.subroute',
})

Check it here

Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • Thank you, Radim, for you time. We are almost there, but not quite yet. In your example there is a case when I navigate to 'page2', then 'tabId1/2/3' then 'page2' again. - 'root.page2.tab' and 'root.page2.tab.subroute' are not activated any more. Though it works fine once we route 'page1' and 'page2' again. (Same case for both approaches). Any thoughts? –  Jun 16 '15 at 11:45
  • The point is: going from tabs 1 / 2 / 3 back to page2... does not re-run the 'Page2Controller'. This is their parent, so when going back from child ... parent is still there... not re-init. That's in fact good. Do you really need navigate to some child once this parent is selected? e.g. to Tab 2? Just asking.. could you confirm that this is a must for you? – Radim Köhler Jun 16 '15 at 11:55
  • 1 minute please... I'll explain –  Jun 16 '15 at 11:59
  • Check another response, and its plunker... Hope now you'll get what you need ;) – Radim Köhler Jun 16 '15 at 12:04
  • Here is what I actually tried to do http://imgur.com/ltuLAo2. This is what my 'page2' layout should look like. Left bottom list is what I called 'tabId1/2/3'. Graph, filters and table are part of 'page2.tab' view. In fact table is nested inside filters, so table is corresponding to 'page2.tab.subroute' and should be visible all day long regardless of navigation inside 'page' state. Its the first time I make design using ui.router, so I might have made some mistakes. Thank you once again –  Jun 16 '15 at 12:22
1

There is a trick how to handle scenarios:

Parent should trigger some action in case that

  • it is accessed, or
  • its reached again, when navigating back from child in a parent state

In that case, we can use the "target (ui-view) for a child" as a place where sits the special view, with special controller. This will be

  • injected into that position once parent is created and
  • re-injected into that position again, once child is left. In that case, it will be re-init.

Enough explanation. There is a working plunker. There is adjusted state:

.state('root.page2', {
    url: '/page2',
    views: {
      'content@root': {
        templateUrl: './tpl.page2.html',
        controller: 'Page2Controller'
      },
      '@root.page2': {
        template: '<div></div>',
        controller: 'RedirectorController'
      }
    }
})

So, now we can do some magic inside of our 'RedirectorController'

.controller('RedirectorController', ['$scope', '$state', 
   function($scope, $state) {
      $state.go('root.page2.tab', { tabId: $scope.activeTabId });
}])

Check it in action here

Read more about what that new view/controller get from the other (Scope Inheritance by View Hierarchy Only) one here

Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • Didn't quite get the reason why that magic works, but it does! Have to read up on this more. Thank you Radim. –  Jun 16 '15 at 12:13
  • If that helped anyhow ... ;) great. Really ;) Here I tried explain that magic in detail http://stackoverflow.com/a/29115009/1679310 ... maybe that could help that it is a trick... using built-in features... and sadly NO magic ;) – Radim Köhler Jun 16 '15 at 12:44