web-dev-qa-db-fra.com

Comment définir la vue enfant par défaut avec Angular UI Router

Disons que j'ai les 3 Angular UI Router states suivants:

$stateProvider
    .state('adminCompanies', {
        abstract: true,
        url: "/admin/companies",
        template: '<div ui-view class="viewContainer" autoscroll="false" />'
    })
    .state('adminCompanies.list', {
        url: "",
        templateUrl: 'app/admin/companies/companies.list.html',
        controller: 'AdminCompaniesController'
    })
    .state('adminCompanies.detail', {
        url: "/:companyId",
        templateUrl: 'app/admin/companies/companies.detail.html',
        resolve: {
            company: function(Model, $stateParams) {
                return Model.get("/admin/companies", $stateParams.companyId);
            }
        },
        controller: 'AdminCompanyDetailController'
    })

Si le adminCompanies est transféré directement, comment dire à Angular UI Router d'aller au adminCompanies.list à la place?

Idéalement, ce que j'aimerais, c'est quelque chose comme:

$stateProvider.when('adminCompanies', 'adminCompanies.list');

Dans mon code, je veux que $ state.go ('adminCompanies') soit équivalent à $ state.go ('adminCompanies.list')

29
egervari

Comme votre application est actuellement configurée, vous ne devriez pas avoir besoin de logique explicite pour cela. Lorsqu'un sous-état a une propriété url vide, il devient actif en même temps que son état parent devient actif. Tout modèle de sous-état est inséré dans le ui-view directive fournie par le modèle de l'État parent. L'interface utilisateur Angular exemple d'application traite ce type d'architecture: lorsque l'état contacts est parcouru, son modèle fournit la disposition de la navigation ainsi qu'un ui-view pour ses sous-états; parce que le contacts.list l'état a une propriété url de "", il est automatiquement chargé lorsque son état parent, contacts est parcouru. Ceci est documenté dans les commentaires de l'application:

L'utilisation d'une URL vide signifie que cet état enfant deviendra actif lorsque l'URL de son parent sera parcourue. Les URL des états enfants sont automatiquement ajoutées aux URL de leurs parents. L'URL de cet état est donc '/ contacts' (car '/ contacts' + '').

Maintenant, en supposant pour une raison ou une autre que vous vous n'avez jamais voulu que l'état parent adminCompanies devienne actif. Dans ce cas, vous pouvez faire de cet état un état abstrait comme ceci:

$stateProvider
    .state('adminCompanies', {
        abstract: true,
        url: "/admin/companies",
        template: '<div ui-view class="viewContainer" autoscroll="false" />'
    })
    .state('adminCompanies.list', {
        url: "/list",
        templateUrl: 'app/admin/companies/companies.list.html',
        controller: 'AdminCompaniesController'
    })
    .state('adminCompanies.detail', {
        url: "/:companyId",
        templateUrl: 'app/admin/companies/companies.detail.html',
        resolve: {
            company: function(Model, $stateParams) {
                return Model.get("/admin/companies", $stateParams.companyId);
            }
        },
        controller: 'AdminCompanyDetailController'
    })

Notez l'ajout de abstract: true ajout sur la 3ème ligne et l'URL d'état explicite de /list pour adminCompanies.list

Cela indique à Angular-UI qu'il doit traiter cet état comme s'il n'existait pas à des fins de navigation URL. Cependant, il restera actif lorsque vous naviguerez vers des sous-états, il utilisera donc toujours l'URL que vous fournissez pour préfixer l'URL des sous-états. Mais si vous essayez d'y accéder à partir d'un autre état, cela agira comme si l'état n'existait pas. Pour cette raison, vous devrez également ajouter la gestion des URL sans correspondance à l'aide de $urlRouteProvider.

Une utilisation basique de $urlRouteProvider pourrait ressembler à ceci:

$urlRouterProvider.otherwise("/")

Cela redirige simplement tous les appels vers des états inexistants vers l'état avec l'URL "/". Cela suppose que vous en avez un. Cependant, parce que quelqu'un essaie peut-être d'accéder à la vue liste mais navigue vers /admin/companies directement, vous devriez probablement avoir un gestionnaire comme celui-ci:

$urlRouterProvider.when("/admin/companies", "/admin/companies/list");

Celui que vous utilisez dépend de l'architecture de votre application, mais il semble que pour vos besoins actuels, vous ne devriez rien faire. Si vos spécifications changent, l'état abstrait pourrait être utile.

39
David Antaramian

Vous pouvez également utiliser i-router-default - un module où les états enfants par défaut sont définis dans l'état parent en définissant abstract: ".defaultChild".

Cela a l'avantage de pouvoir utiliser ui-sref="parent" Et $state.go("parent"); (ce qui était important pour moi lors de la création dynamique d'une barre de navigation).

NB: ceci et la solution de David ne fonctionnent que si l'état parent est abstrait - c'est-à-dire que le parent ne peut pas être actif sans qu'un enfant soit actif - ce qui devrait être le cas lorsque nous voulons avoir une vue enfant "par défaut".

(Voir aussi la discussion pertinente de l'équipe ui-router ici .)

2
StevieP

Dans la version 1.0.0alpha0 ils le rendent enfin possible! Pas enfant pour les états abstraits, nouveau $ transitionsProvider , dans lequel vous pouvez définir onBefore crochet. Vous pouvez modifier le comportement en fonction des options d'état.

Par exemple, vous pouvez modifier le comportement du paramètre "abstrait":

 $transitionsProvider.onBefore({
    to: state => !!state.abstract
  }, ($transition$, $state) => {
    if (angular.isString($transition.to().abstract)) {
      return $state.target($transition.to().abstract);
    }
  });

et l'utiliser comme ça:

  abstract: 'abstract2.foo',  //use not boolean but exact child state

exemple de code

provient de: i-router: enfant par défaut pour l'état abstrait

1
Stepan Suvorov