Направление пользователя в дочернее состояние при переходе в его родительское состояние с использованием 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?

Ответ 1

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

  • Затем выполните один следующее:

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

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

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

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

Ответ 2

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

Ответ 3

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

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

Ниже приведен анализ того, как работает этот процесс:

  • Пользователь переходит в режим "родительский" Событие
  • "$ stateChangeStart" запускается
  • Слушатель для "$ stateChangeStart" ловит событие и передает "toState" (который является "родителем" ) и "событие" в функцию обработчика
  • Функция обработчика проверяет, установлено ли "redirectTo" на "toState" .
  • Если "redirectTo" НЕ установлен, ничего не происходит, и пользователь переходит в состояние "toState" .
  • Если установлено "redirectTo" IS, событие отменяется (event.preventDefault), а $state.go(toState.redirectTo) отправляет их в состояние, указанное в "redirectTo" (которое является "parent.child" ).
  • Событие "$ StateChangeStart" снова запускается, но на этот раз "toState" == "parent.child" и параметр "redirectTo" не установлены, поэтому он продолжает "toState" .

Ответ 4

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

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

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

Ответ 5

Я изменил 'manager.staffDetial.view' на абстрактное состояние и оставил 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'}})

Ответ 6

В "angular -ui-router": "0.2.13", я не думаю, что решение @nfiniteloop redirect будет работать. Он работал, как только я вернулся к 0.2.12 (и, возможно, пришлось поместить $urlRouterProvider.when позвонить перед $stateProvider?)

см. fooobar.com/questions/78579/...

и fooobar.com/questions/78586/... для обходного пути (если вы не хотите возвращаться к 0.2.12)

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

Ответ 7

здесь очень простая и прозрачная альтернатива, просто изменяя родительское состояние в 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: '....'
  })

Ответ 8

Добавьте 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/> где-то в нем.

Ответ 9

Поздно, но все ответы здесь не относятся к последней версии 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

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