Redirect a state to default substate with UI-Route

2019-01-01 05:26发布

问题:

I\'m creating a tab based page which shows some data. I\'m using UI-Router in AngularJs to register states.

My aim is to have one default tab open on page load. Each tab have sub tabs, and I would like to have a default sub tab open when changing tabs.

I was testing with onEnter function and inside I\'m using $state.go(\'mainstate.substate\'); but it seems not to work due to loop effect issues (on state.go to substate it calls its parent state and so on, and it turns in a loop).

$stateProvider

.state(\'main\', {
  url: \'/main\',
  templateUrl: \'main.html\',
  onEnter: function($state) {
    $state.go(\'main.street\');
  }
})

.state(\'main.street\', {
  url: \'/street\',
  templateUrl: \'submenu.html\',
  params: {tabName: \'street\'}
})

Here I created a plunker demo.

For now everything works, except that I don\'t have default tab open and that\'s exactly what I need.

Thank you for your suggestions, opinions and ideas.

回答1:

I created an example here.

This solution comes from a nice \"Comment\" to an an issue with redirection using .when() (https://stackoverflow.com/a/27131114/1679310) and really cool solution for it (by Chris T, but the original post was by yahyaKacem)

https://github.com/angular-ui/ui-router/issues/1584#issuecomment-75137373

So firstly let\'s extend main with redirection setting:

$stateProvider
    .state(\'main\', {
      url: \'/main\',
      templateUrl: \'main.html\',
      redirectTo: \'main.street\',
    })

And add only this few lines into run

app.run([\'$rootScope\', \'$state\', function($rootScope, $state) {

    $rootScope.$on(\'$stateChangeStart\', function(evt, to, params) {
      if (to.redirectTo) {
        evt.preventDefault();
        $state.go(to.redirectTo, params, {location: \'replace\'})
      }
    });
}]);

This way we can adjust any of our states with its default redirection...Check it here

EDIT: Added option from comment by @Alec to preserve the browser history.



回答2:

In fact even if this solution proposed by Radim did exactly the job, I needed to remember every tab\'s sub tab (state).

So I found another solution which do the same thing but also remembers every tab substate.

I all have to do was to install ui-router-extras and use the deep state redirect feature:

$stateProvider
  .state(\'main.street\', {
     url: \'/main/street\',
     templateUrl: \'main.html\',
     deepStateRedirect: { default: { state: \'main.street.cloud\' } },
  });

Thank you!



回答3:

As of version 1.0 of the ui-router it supports a redirectTo property. For example:

.state(\'A\', {
  redirectTo: \'A.B\'
})


回答4:

Since version 1.0 of ui-router, a default hook has been introduced using IHookRegistry.onBefore() as demonstrated in the example Data Driven Default Substate in http://angular-ui.github.io/ui-router/feature-1.0/interfaces/transition.ihookregistry.html#onbefore

// state declaration
{
  name: \'home\',
  template: \'<div ui-view/>\',
  defaultSubstate: \'home.dashboard\'
}

var criteria = {
  to: function(state) {
    return state.defaultSubstate != null;
  }
}
$transitions.onBefore(criteria, function($transition$, $state) {
  return $state.target($transition$.to().defaultSubstate);
});


回答5:

app.config(function($stateProvider,$urlRouterProvider){

    $urlRouterProvider.when(\"/state\",\"/state/sub-state\");

    })


回答6:

If someone comes here for an answer regarding how to implement a simple redirect for a state and, as it happened to me, doesn\'t have the opportunity to use the new router...

Obviously again if you can, @bblackwo answer is great:

$stateProvider.state(\'A\', {
  redirectTo: \'B\',
});

If you can\'t then just manually redirect it:

$stateProvider.state(\'A\', {
  controller: $state => {
    $state.go(\'B\');
  },
});

I hope it helps!