Направление пользователя в дочернее состояние при переходе в родительское состояние с помощью UI-Router


рассмотрим следующее:

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

Если я пойду к domain.com/staff/1234/view, Как я могу по умолчанию manager.staffDetail.view.schedule состояние ребенка?

9 72

9 ответов:

  1. во-первых, добавьте свойство к 'manager.staffDetail.view' состояние abstract:true. Это не требуется, но вы хотите установить это, так как вы никогда не перейдете в это состояние напрямую, вы всегда будете переходить в одно из его дочерних состояний.

  2. затем сделать один следующее:

    • дать 'manager.staffDetail.view.schedule' состояние пустой URL. Это позволит ему соответствовать тому же url-адресу, что и url-адрес родительского состояния, потому что он добавляет ничего для родительского url.

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

    • или если вы хотите сохранить url-адрес дочернего маршрута по умолчанию без изменений, а затем настроить редирект в вашем модуле.конфиг. Этот код здесь перенаправит любое местоположение '/staff/{id}/view' в расположении '/staff/{id}/view/schedule':

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

для установки дочернего представления по умолчанию , проверьте это пример . При нажатии Route 1 загрузить состояние по умолчанию 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"];
    }
  })

я столкнулся с той же проблемой и нашел это решение для работы:

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

это цитируется из @christopherthielen на github

" пока не объявляйте свое состояние абстрактным и используйте этот рецепт:"

 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"
  });

вот разбивка того, как работает процесс:

  1. пользователь переходит в состояние "родитель"
  2. событие"$stateChangeStart " уволено
  3. прослушиватель для "$stateChangeStart "ловит событие и передает" toState "(который является "родителем") и "событие" в функцию обработчика
  4. функция обработчика проверяет, установлен ли" redirectTo "на"toState".
  5. если " redirectTo "не установлен, ничего не происходит, и пользователь продолжает состояние" toState".
  6. если установлен параметр "redirectTo", событие отменяется (event.метод preventDefault) и $государство.идти(к.redirectTo) отправляет их в состояние, указанное в "redirectTo" (которое является "родительским.ребенок.)"
  7. событие "$stateChangeStart "запускается снова, но на этот раз" toState "= = " parent.child "и параметр" redirectTo "не установлен, поэтому он продолжает"toState".

довольно поздно, но я думаю, что вы можете "перенаправить" в нужное состояние.

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

вы можете написать вам контроллер прямо в конфигурации состояния для краткости.

Я сменил менеджера.staffDetial.просмотр "в абстрактное состояние и оставил url-адрес моего дочернего состояния по умолчанию пустым"

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

в "угловой пользовательского интерфейса маршрутизатора": "0.2.13", я не думаю, что @nfiniteloop направить решение будет работать. Он работал, как только я откатился до 0.2.12 (и, возможно, пришлось поставить $urlRouterProvider.когда звонить перед $stateProvider?)

см.https://stackoverflow.com/a/26285671/1098564

и https://stackoverflow.com/a/27131114/1098564 для обходного пути (если вы не хотите возвращаться к 0.2.12)

по состоянию на 28 ноября 2014, https://github.com/angular-ui/ui-router/issues/1584 указывает, что он должен работать снова в 0.2.14

Это поздно, но все ответы здесь не относятся к последней версии angular-ui-router для AngularJS. По состоянию на это версии (в частности, @uirouter / angularjs#v1.0.x можно просто поставить redirectTo: 'childStateName' во втором параме $stateProvider.state(). Например:

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

вот соответствующий раздел документа:https://ui-router.github.io/guide/ng1/migrate-to-1_0#state-hook-redirectto

надеюсь, это кому-то поможет!

вот очень простая и прозрачная альтернатива, просто изменив родительское состояние в ui router:

  .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: '....'
  })

добавить angular-ui-router-default и добавить abstract и default параметры для родительского состояния:

...

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

...

Примечание: Для этого, чтобы работать, Родительский шаблон должен иметь <ui-view/> где-то в нем.