Rediriger un état vers le sous-état par défaut avec UI-Router dans AngularJS

89

Je crée une page basée sur des onglets qui affiche certaines données. J'utilise UI-Router dans AngularJs pour enregistrer des états.

Mon objectif est d'avoir un onglet par défaut ouvert lors du chargement de la page. Chaque onglet a des sous-onglets, et je voudrais avoir un sous-onglet par défaut ouvert lors du changement d'onglet.

J'étais en train de tester avec la onEnterfonction et à l'intérieur que j'utilise, $state.go('mainstate.substate');mais cela ne semble pas fonctionner en raison de problèmes d'effet de boucle (sur state.go pour remplacer, il appelle son état parent et ainsi de suite, et il se transforme en boucle).

$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'}
})

Ici, j'ai créé une démo de plunker .

Pour l'instant, tout fonctionne, sauf que je n'ai pas l'onglet par défaut ouvert et c'est exactement ce dont j'ai besoin.

Merci pour vos suggestions, opinions et idées.

Leo
la source

Réponses:

172

Mise à jour: 1.0 Prend en charge la redirection vers la sortie de la boîte.

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


J'ai créé un exemple ici .

Cette solution vient d'un joli "Commentaire" à un problème de redirection en utilisant .when() ( https://stackoverflow.com/a/27131114/1679310 ) et une solution vraiment cool pour cela (par Chris T, mais le message original était par yahyaKacem)

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

Alors tout d'abord, étendons main avec le paramètre de redirection:

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

Et n'ajoutez que ces quelques lignes dans la course

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

De cette façon, nous pouvons ajuster l'un de nos états avec sa redirection par défaut ... Vérifiez-le ici

EDIT: Ajout d'une option du commentaire de @Alec pour préserver l'historique du navigateur.

Radim Köhler
la source
4
Cela semble clobber le bouton de retour.
Scott Sword
6
@ Swordfish0321 pour corriger le bouton de retour, faites ce petit changement: $state.go(to.redirectTo, params, {location: 'replace'});Cela fera remplacer l'état précédent (c'est-à-dire celui depuis lequel nous sommes redirigés) dans l'historique. Voir la documentation pour $ state.go: angular-ui.github.io/ui-router/site/#/api/…
Alec
2
Je voulais juste ajouter que c'était très proche de ce que je voulais faire, mais je voulais l'URL par défaut au lieu de la remplacer, cela a été facilement accompli en changeant '$stateChangeStart'en'$stateChangeSuccess'
Matti Price
6
ui-router 1.0 a un support intégré pour cela: ui-router.github.io/guide/ng1
Gert-Jan
21

En fait, même si cette solution proposée par Radim faisait exactement le travail, je devais me souvenir du sous-onglet (état) de chaque onglet.

J'ai donc trouvé une autre solution qui fait la même chose mais se souvient également de chaque sous-état d'onglet.

Tout ce que j'ai à faire était d'installer ui-router-extras et d'utiliser la fonction de redirection d'état profond :

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

Je vous remercie!

Leo
la source
12

Depuis la version 1.0 de l'interface utilisateur, il prend en charge une redirectTopropriété. Par exemple:

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

Depuis la version 1.0 de ui-router, un hook par défaut a été introduit en utilisant IHookRegistry.onBefore () comme illustré dans l'exemple Data Driven Default Substate dans 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);
});
ThmX
la source
Ce genre de travail pour moi, même si, j'ai dû le peaufiner (également en utilisant 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
la source
1
Pouvez-vous expliquer ce que cela fait et pourquoi c'est mieux que les réponses déjà existantes?
Equalsk
Cette solution est la plus simple et a bien fonctionné pour moi.
BuffMcBigHuge
C'est de loin la meilleure réponse. Plus concis que d'utiliser des événements de changement. Pas besoin d'ajouter des packages. Je ne sais pas comment cela n'est clair pour personne. Je ne sais pas comment la réponse acceptée a été autant votée.
CodeWarrior
1

Si quelqu'un vient ici pour une réponse sur la façon d'implémenter une simple redirection pour un état et, comme cela m'est arrivé, n'a pas la possibilité d'utiliser le nouveau routeur ...

De toute évidence, si vous le pouvez, la réponse @bblackwo est excellente:

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

Si vous ne pouvez pas le rediriger manuellement:

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

J'espère que ça aide!

Jose Daniel Vivar Personat
la source