简体   繁体   中英

UI-router accessing parent state from child

I'd like to set the title based on the state in my angular app. It works nicely, but if there's no title defined on the child state, I'd like to fall back to the parent's title property.

This is what I have so far:

In my app run block:

...
$rootScope.$on('$stateChangeSuccess', function (event, current, previous) {

  if (current.hasOwnProperty('title')) {
    $rootScope.title = current.title;
  }
});
...

In my module's route

.state('main.parent', {
  url: '/parent',
  controller: 'ParentController',
  controllerAs: 'vm',
  templateUrl: 'app/parent.html',
  title: 'Parent',
})
.state('main.parent.child', {
  url: '/child',
  controller: 'ChildController',
  controllerAs: 'vm',
  templateUrl: 'app/child.html'
})

During the code inspection, I found that $stateChangeSuccess is triggered twice as expected, first for the parent and then for the child. I tried to access current.parent when the child was called, but it has no such property. Is there any way to access it?

UPDATE

I saw these questions: get parent state from ui-router $stateChangeStart , get parent state from ui-router $stateChangeStart But none of them had a clear answer to this problem (except the state splitting hack in the latter one but I'd rather avoid that).

The both ways are hacks a bit. Don't forget to import $state (and $stateParams for 2nd variant) providers in your controller. You can use:

$state.$current.parent.self.title 

or

var tree = current.name.split('.');
tree.splice(tree.length-1, 1);
var parent = tree.join('.');
$state.get(parent, $stateParams);

如果子状态上没有定义title ,您似乎只需要title属性来回退到父级的 title 属性,我建议您使用这个存储库: angular-ui-router-title

So finally I came up with the following solution:

I store title inside the state's data object, because from $state you can't access the parent's custom properties, only the ones stored in data (which makes sense - not to pollute the state definition with custom properties).

.state('main.parent', {
  url: '/parent',
  controller: 'ParentController',
  controllerAs: 'vm',
  templateUrl: 'app/parent.html',
  data: {
    title: 'Parent'
  }
})
.state('main.parent.child', {
  url: '/child',
  controller: 'ChildController',
  controllerAs: 'vm',
  templateUrl: 'app/child.html'
})

And I changed the runblock as follows:

...
$rootScope.$on('$stateChangeSuccess', function (event, toState, fromState) {
  var current = $state.$current;
  if (current.data.hasOwnProperty('title')) {
    $rootScope.title = current.data.title;
  } else if(current.parent && current.parent.data.hasOwnProperty('title')) {
    $rootScope.title = current.parent.data.title;
  } else {
    $rootScope.title = null;
  }
});
...

This is not the perfect solution yet, as in the case of multiple nested states it'd be nice to fall back to the title of the youngest ancestor's title but it does it for now.

Simply below code is working for me

$state.$current.parent

Looking at the UI-Router documentation in the "to" section, you could do something like below:

$state.go('^');

to go back to the parent state.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM