Reindirizza uno stato al sottostato predefinito con UI-Router in AngularJS


89

Sto creando una pagina basata su schede che mostra alcuni dati. Sto usando UI-Router in AngularJs per registrare gli stati.

Il mio scopo è avere una scheda predefinita aperta al caricamento della pagina. Ogni scheda ha sottoschede e vorrei avere una sottoscheda predefinita aperta quando si cambia scheda.

Stavo testando con la onEnterfunzione e all'interno lo sto usando $state.go('mainstate.substate');ma sembra non funzionare a causa di problemi di effetto loop (su state.go per substate chiama il suo stato genitore e così via, e si trasforma in un 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'}
})

Qui ho creato una demo di plunker .

Per ora tutto funziona, tranne che non ho la scheda predefinita aperta ed è esattamente quello che mi serve.

Grazie per i tuoi suggerimenti, opinioni e idee.

Risposte:


172

Aggiornare: 1.0 in poi Supporta il reindirizzamento a fuori dalla scatola.

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


Ho creato un esempio qui .

Questa soluzione deriva da un simpatico "Commento" a un problema con il reindirizzamento utilizzando .when() ( https://stackoverflow.com/a/27131114/1679310 ) e una soluzione davvero interessante (di Chris T, ma il post originale era di yahyaKacem)

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

Quindi per prima cosa estendiamo main con l'impostazione di reindirizzamento:

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

E aggiungi solo queste poche righe in 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'})
      }
    });
}]);

In questo modo possiamo regolare qualsiasi nostro stato con il suo reindirizzamento predefinito ... Controllalo qui

MODIFICA: aggiunta opzione dal commento di @Alec per preservare la cronologia del browser.


4
Questo sembra schiacciare il pulsante Indietro.
Scott Sword

6
@ Swordfish0321 per correggere il pulsante Indietro, apporta questa piccola modifica: $state.go(to.redirectTo, params, {location: 'replace'});questo farà sì che il nuovo stato sostituisca lo stato precedente (cioè quello da cui veniamo reindirizzati) nella cronologia. Vedi i documenti per $ state.go: angular-ui.github.io/ui-router/site/#/api/…
Alec

2
Volevo solo aggiungere che questo era molto vicino a quello che volevo fare, ma volevo l'URL predefinito invece di sostituirlo, questo è stato facilmente ottenuto cambiando '$stateChangeStart'in'$stateChangeSuccess'
Prezzo Matti

6
ui-router 1.0 ha il supporto integrato per questo: ui-router.github.io/guide/ng1/…
Gert-Jan

21

Infatti anche se questa soluzione proposta da Radim esattamente, avevo bisogno di ricordare la sottoscheda (stato) di ogni scheda.

Quindi ho trovato un'altra soluzione che fa la stessa cosa ma ricorda anche ogni sottostato di tabulazione.

Tutto quello che dovevo fare era installare ui-router-extra e utilizzare la funzione di reindirizzamento dello stato profondo :

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

Grazie!


12

A partire dalla versione 1.0 dell'interfaccia utente-router supporta una redirectToproprietà. Per esempio:

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

7

Dalla versione 1.0 di ui-router, è stato introdotto un hook predefinito utilizzando IHookRegistry.onBefore () come dimostrato nell'esempio Data Driven Default Substate in 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);
});

Questo tipo di lavoro per me, anche se, ho dovuto modificarlo (anche 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");

    })

1
Puoi fornire una spiegazione su cosa fa e perché è migliore delle risposte già esistenti?
Equalsk

Questa soluzione è la più semplice e ha funzionato bene per me.
BuffMcBigHuge

Questa è di gran lunga la migliore risposta. Più conciso rispetto all'utilizzo di eventi di cambiamento. Non è necessario aggiungere pacchetti. Non so come non sia chiaro a nessuno. Non so come la risposta accettata sia stata votata così tanto.
CodeWarrior

1

Se qualcuno viene qui per una risposta su come implementare un semplice reindirizzamento per uno stato e, come è successo a me, non ha la possibilità di utilizzare il nuovo router ...

Ovviamente di nuovo se puoi, la risposta di @bblackwo è fantastica:

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

Se non puoi, reindirizzalo manualmente:

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

Spero possa essere d'aiuto!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.