Redirecione um estado para o subestado padrão com UI-Router em AngularJS

89

Estou criando uma página baseada em guia que mostra alguns dados. Estou usando o UI-Router em AngularJs para registrar estados.

Meu objetivo é ter uma guia padrão aberta no carregamento da página. Cada guia possui subguias, e eu gostaria de ter uma subguia padrão aberta ao mudar de guia.

Eu estava testando com onEnter função e por dentro estou usando, $state.go('mainstate.substate');mas parece não funcionar devido a problemas de efeito de loop (em state.go para subestado, ele chama seu estado pai e assim por diante, e se transforma em um 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'}
})

Aqui eu criei uma demonstração do plunker .

Por enquanto, tudo funciona, exceto que não estou com a guia padrão aberta e é exatamente disso que preciso.

Obrigado por suas sugestões, opiniões e idéias.

Leo
fonte

Respostas:

172

Atualização: 1.0 em diante Suporta redirectTo fora da caixa.

https://ui-router.github.io/ng1/docs/latest/interfaces/state.statedeclaration.html#redirectto


Criei um exemplo aqui .

Esta solução vem de um bom "Comentário" para um problema com redirecionamento usando .when() ( https://stackoverflow.com/a/27131114/1679310 ) e uma solução muito legal para ele (por Chris T, mas a postagem original foi por yahyaKacem)

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

Então, primeiro vamos estender o main com a configuração de redirecionamento:

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

E adicione apenas algumas linhas para executar

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

Desta forma podemos ajustar qualquer um dos nossos estados com o seu redirecionamento padrão ... Confira aqui

EDITAR: Adicionada opção de comentário de @Alec para preservar o histórico do navegador.

Radim Köhler
fonte
4
Isso parece derrubar o botão Voltar.
Scott Sword
6
@ Swordfish0321 para corrigir o botão Voltar, faça esta pequena mudança: $state.go(to.redirectTo, params, {location: 'replace'});Isso fará com que o novo estado substitua o estado anterior (ou seja, aquele de onde estamos sendo redirecionados) no histórico. Veja os documentos de $ state.go: angular-ui.github.io/ui-router/site/#/api/…
Alec
2
Só queria acrescentar que isso era bem próximo do que eu queria fazer, mas eu queria o URL padrão em vez de substituí-lo, isso foi facilmente realizado mudando '$stateChangeStart'para'$stateChangeSuccess'
Matti Price
6
ui-router 1.0 tem suporte integrado para isto: ui-router.github.io/guide/ng1/…
Gert-Jan
21

Na verdade, mesmo que essa solução proposta por Radim fizesse exatamente o trabalho, eu precisava lembrar de cada subguia (estado) de cada guia.

Então eu encontrei outra solução que faz a mesma coisa, mas também lembra cada subestado de guia.

Tudo o que eu tive que fazer foi instalar ui-router-extras e usar o recurso de redirecionamento de estado profundo :

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

Obrigado!

Leo
fonte
12

A partir da versão 1.0 do ui-router, ele oferece suporte a uma redirectTopropriedade. Por exemplo:

.state('A', {
  redirectTo: 'A.B'
})
BBlackwo
fonte
7

Desde a versão 1.0 do ui-router, um gancho padrão foi introduzido usando IHookRegistry.onBefore () como demonstrado no exemplo Data Driven Default Substate em http://angular-ui.github.io/ui-router/feature-1.0/ interfaces / transaction.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);
});
ThmX
fonte
Este tipo de trabalho para mim, embora, eu tive que ajustá-lo (também usando ES6)$transitions.onBefore({ to: state => state.defaultSubstate != null }, trans => trans.router.stateService.target(trans.to().defaultSubstate));
yorch
3
app.config(function($stateProvider,$urlRouterProvider){

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

    })
shubam yadav
fonte
1
Você pode fornecer uma explicação sobre o que isso faz e por que é melhor do que as respostas já existentes?
Equalsk em
Esta solução é a mais fácil e funcionou bem para mim.
BuffMcBigHuge
Esta é a melhor resposta de longe. Mais conciso do que usar eventos de mudança. Não há necessidade de adicionar pacotes. Não sei como isso não está claro para ninguém. Não sei como a resposta aceita foi tão votada.
CodeWarrior
1

Se alguém vier aqui para obter uma resposta sobre como implementar um redirecionamento simples para um estado e, como aconteceu comigo, não tiver a oportunidade de usar o novo roteador ...

Obviamente, se você puder, a resposta @bblackwo é ótima:

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

Se você não puder, basta redirecioná-lo manualmente:

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

Espero que ajude!

Jose Daniel Vivar Personat
fonte