web-dev-qa-db-fra.com

Diriger l'utilisateur vers un état enfant lorsqu'il passe à l'état parent à l'aide de UI-Router

Considérer ce qui suit:

.state('manager.staffList', {url:'^/staff?alpha', templateUrl: 'views/staff.list.html', data:{activeMenu: 'staff'}, controller: 'staffListCtrl'})
.state('manager.staffDetail', {url:'^/staff/{id}' , templateUrl: 'views/staff.html', data:{activeMenu: 'staff'}, controller: 'staffDetailsCtrl'})
  .state('manager.staffDetail.view', {url:'/view',  templateUrl: 'views/staff.details.html', data:{activeMenu: 'staff'}})
    .state('manager.staffDetail.view.schedule', {url:'/schedule', templateUrl:'views/staff.view.schedule.html', data:{activeMenu: 'staff'}})
    .state('manager.staffDetail.view.history', {url:'/history' , templateUrl:'views/staff.view.history.html', data:{activeMenu: 'staff'}})
    .state('manager.staffDetail.view.log', {url:'/log', templateUrl:'views/staff.view.log.html', data:{activeMenu: 'staff'}})
    .state('manager.staffDetail.view.files', {url:'/files', templateUrl:'views/staff.view.files.html', data:{activeMenu: 'staff'}})
  .state('manager.staffDetail.edit', {url:'/edit',  templateUrl: 'views/staff.edit.html', data:{activeMenu: 'staff'}})

Si je vais à domain.com/staff/1234/view, comment puis-je passer par défaut à l'état enfant manager.staffDetail.view.schedule?

73
Meeker
  1. Tout d’abord, ajoutez une propriété à l’état _'manager.staffDetail.view'_ de abstract:true. Ce n'est pas obligatoire, mais vous voulez définir ceci car vous n'irez jamais directement dans cet état, vous irez toujours dans l'un de ses états enfants.

  2. Alors faites n de ce qui suit:

    • Indiquez à l'état _'manager.staffDetail.view.schedule'_ un RL vide. Cela fera en sorte qu'il corresponde à la même URL que l'URL de l'état parent, car il n'ajoute rien à l'URL parent.

      _.state('manager.staffDetail.view.schedule', {url:'', ..._

    • Ou si vous souhaitez que l'URL de la route enfant par défaut ne soit pas modifiée, configurez un redirect dans votre module.config. Ce code ici redirige n'importe quel emplacement de _'/staff/{id}/view'_ vers l'emplacement de _'/staff/{id}/view/schedule'_:

      $urlRouterProvider.when('/staff/{id}/view', '/staff/{id}/view/schedule');

136
Tim Kindberg

Pour définir la vue enfant par défaut, vérifiez cet exemple exemple . En cliquant sur Route 1 charger l'état par défaut route1.list

// For any unmatched url, send to /route1
$stateProvider
  .state('route1', {
      url: "/route1",
      abstract:true ,
      templateUrl: "route1.html"
  })
  .state('route1.list', {
      url: '',
      templateUrl: "route1.list.html",
      controller: function($scope){
        $scope.items = ["A", "List", "Of", "Items"];
      }
  })
  .state('route1.desc', {
      url: "/desc",
      templateUrl: "route1.desc.html",
      controller: function($scope){
        $scope.items = [];
      }
  })
  .state('route2', {
    url: "/route2",
    templateUrl: "route2.html"
  })
  .state('route2.list', {
    url: "/list",
    templateUrl: "route2.list.html",
    controller: function($scope){
      $scope.things = ["A", "Set", "Of", "Things"];
    }
  })
20
rab

J'ai rencontré le même problème et j'ai trouvé cette solution efficace:

https://github.com/angular-ui/ui-router/issues/948#issuecomment-75342784

Ceci est cité de @christopherthielen sur github

"Pour l'instant, ne déclarez pas votre résumé d'état et utilisez cette recette:"

 app.run($rootScope, $state) {
    $rootScope.$on('$stateChangeStart', function(evt, to, params) {
      if (to.redirectTo) {
        evt.preventDefault();
        $state.go(to.redirectTo, params)
      }
    });
  }

  $stateProvider.state('parent' , {
      url: "/parent",
      templateUrl: "parent.html",
      redirectTo: 'parent.child'
  });

  $stateProvider.state('parent.child' , {
      url: "/child",
      templateUrl: "child.html"
  });

Voici le détail du fonctionnement du processus:

  1. L'utilisateur navigue pour indiquer «parent»
  2. L'événement “$ stateChangeStart” est déclenché
  3. Le programme d'écoute de «$ stateChangeStart» intercepte un événement et transmet «toState» (qui est «parent») et «événement» à la fonction de gestionnaire
  4. La fonction de gestionnaire vérifie si «redirectTo» est défini sur «toState».
  5. Si «redirectTo» IS N'EST PAS défini, rien ne se passe et l'utilisateur passe à l'état «toState».
  6. Si "redirectTo" IS est défini, l'événement est annulé (event.preventDefault) et $ state.go (toState.redirectTo) les envoie à l'état spécifié dans "redirectTo" ("parent.child").
  7. L'événement “$ stateChangeStart” est à nouveau déclenché, mais cette fois-ci “toState” == “parent.child” et l'option “redirectTo” ne sont pas définis et sont donc maintenus à “toState”.
8
Chuck D

Assez tard, mais je pense que vous pouvez "rediriger" vers l’état que vous souhaitez. 

.state('manager.staffDetail.view', {
    url:'/view',
    templateUrl: 'views/staff.details.html',
    controller: 'YourController'
})

app.controller('YourController', ['$state',
function($state) {
    $state.go('manager.staffDetail.view.schedule');
}]);

Vous pouvez écrire votre contrôleur directement dans la configuration d’état.

7
nvcnvn

J'ai remplacé 'manager.staffDetial.view' par un état abstrait et laissé en blanc l'URL de mon état enfant par défaut ''

// Staff
.state('manager.staffList',    {url:'^/staff?alpha',      templateUrl: 'views/staff.list.html', data:{activeMenu: 'staff'}, controller: 'staffListCtrl'})
.state('manager.staffDetail',   {url:'^/staff/{id}', templateUrl: 'views/staff.html', data:{activeMenu: 'staff'}, controller: 'staffDetailsCtrl'})
.state('manager.staffDetail.view',   {url:'/view', abstract: true, templateUrl: 'views/staff.details.html', data:{activeMenu: 'staff'}})
    .state('manager.staffDetail.view.schedule', {url:'', templateUrl:'views/staff.view.schedule.html', data:{activeMenu: 'staff'}})
    .state('manager.staffDetail.view.history', {url:'/history', templateUrl:'views/staff.view.history.html', data:{activeMenu: 'staff'}})
    .state('manager.staffDetail.view.log', {url:'/log', templateUrl:'views/staff.view.log.html', data:{activeMenu: 'staff'}})
    .state('manager.staffDetail.view.files', {url:'/files', templateUrl:'views/staff.view.files.html', data:{activeMenu: 'staff'}})
.state('manager.staffDetail.edit',   {url:'/edit',  templateUrl: 'views/staff.edit.html', data:{activeMenu: 'staff'}})
3
Meeker

Dans "angular-ui-router": "0.2.13", je ne pense pas que la solution de redirection de @ nfiniteloop fonctionnera. Cela a fonctionné une fois que je suis revenu à 0.2.12 (et il a peut-être fallu mettre $ urlRouterProvider.when call avant $ StateProvider?)

voir https://stackoverflow.com/a/26285671/1098564

et https://stackoverflow.com/a/27131114/1098564 pour une solution de contournement (si vous ne souhaitez pas revenir à la version 0.2.12)

au 28 nov. 2014, https://github.com/angular-ui/ui-router/issues/1584 indique que cela devrait fonctionner à nouveau dans 0.2.14

1
sdoxsee

C'est tard, mais toutes les réponses ici ne s'appliquent pas à la dernière version de angular-ui-router pour AngularJS. A partir de la version that (en particulier @ uirouter/angularjs # v1.0.x vous pouvez simplement mettre redirectTo: 'childStateName' dans le deuxième paramètre de $stateProvider.state(). Par exemple:

$stateProvider
.state('parent', {
  resolve: {...},
  redirectTo: 'parent.defaultChild'
})
.state('parent.defaultChild', {...})

Voici la section doc correspondante: https://ui-router.github.io/guide/ng1/migrate-to-1_0#state-hook-redirectto

Espérons que cela aide quelqu'un!

1
AndyPerlitch

Ajoutez angular-ui-router-default et ajoutez les options abstract et default à l'état parent:

...

.state('manager.staffDetail.view', {abstract: true, default: '.schedule', url:'/view',  templateUrl: 'views/staff.details.html', data:{activeMenu: 'staff'}})
  .state('manager.staffDetail.view.schedule', {url:'/schedule', templateUrl:'views/staff.view.schedule.html', data:{activeMenu: 'staff'}})

...

Remarque: pour que cela fonctionne, le modèle parent doit comporter <ui-view/> quelque part.

0
Jonathon Hill

voici une alternative très simple et transparente en modifiant simplement l’état parent dans le routeur ui: 

  .state('parent_state', {
    url: '/something/:param1/:param2',
    templateUrl: 'partials/something/parent_view.html',  // <- important
    controller: function($state, $stateParams){
      var params = angular.copy($state.params);
      if (params['param3'] === undefined) {
        params['param3'] = 'default_param3';
      }
      $state.go('parent_state.child', params) 
    }
  })

  .state('parent_state.child', {
    url: '/something/:param1/:param2/:param3',
    templateUrl: '....',  
    controller: '....'
  })
0
okigan