Перенаправить состояние в подсостояние по умолчанию с помощью UI-Router в AngularJS


89

Я создаю страницу с вкладками, на которой отображаются некоторые данные. Я использую UI-Router в AngularJs для регистрации состояний.

Моя цель - открыть одну вкладку по умолчанию при загрузке страницы. На каждой вкладке есть вложенные вкладки, и я хотел бы, чтобы вложенная вкладка по умолчанию открывалась при смене вкладок.

Я тестировал onEnterфункцию, и внутри я использую, $state.go('mainstate.substate');но, похоже, она не работает из-за проблем с эффектом цикла (на state.go для подстановки он вызывает свое родительское состояние и так далее, и он превращается в цикл).

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

Здесь я создал демонстрацию плункера .

Пока все работает, за исключением того, что у меня не открыта вкладка по умолчанию, а это именно то, что мне нужно.

Спасибо за ваши предложения, мнения и идеи.

Ответы:


172

Обновление: 1.0 и далее Поддерживает redirectTo из коробки.

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


Я создал здесь пример .

Это решение исходит из приятного «комментария» к проблеме с использованием перенаправления .when() ( https://stackoverflow.com/a/27131114/1679310 ) и действительно классного решения для нее (от Chris T, но исходное сообщение было от yahyaKacem)

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

Итак, сначала давайте расширим main настройкой перенаправления:

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

И добавьте только эти несколько строк в run

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

Таким образом, мы можем настроить любое из наших состояний с перенаправлением по умолчанию ... Отметьте это здесь

EDIT: добавлена ​​опция из комментария @Alec для сохранения истории браузера.


4
Кажется, это сбивает кнопку "Назад".
— Scott Sword

6
@ Swordfish0321, чтобы исправить кнопку «Назад», сделайте это небольшое изменение: $state.go(to.redirectTo, params, {location: 'replace'});это приведет к тому, что новое состояние заменит предыдущее состояние (то есть то, из которого мы перенаправляемся) в истории. См документов для $ state.go: angular-ui.github.io/ui-router/site/#/api/...
— Алек

2
Просто хотел добавить, что это было очень близко к тому, что я хотел сделать, но я хотел использовать URL по умолчанию вместо его замены, это было легко сделать, изменив его '$stateChangeStart'на'$stateChangeSuccess'
— Matti Price

6
ui-router 1.0 имеет встроенную поддержку для этого: ui-router.github.io/guide/ng1/…
— Герт-янв,

21

Фактически, даже если это решение, предложенное Радимом, сработало именно так, мне нужно было запомнить вложенную вкладку (состояние) каждой вкладки.

Итак, я нашел другое решение, которое делает то же самое, но также запоминает каждое подсостояние вкладки.

Все, что мне нужно сделать, это установить ui-router-extras и использовать функцию глубокого перенаправления :

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

Спасибо!



7

Начиная с версии 1.0 ui-router, обработчик по умолчанию был введен с использованием IHookRegistry.onBefore (), как показано в примере подстояния по умолчанию, управляемого данными в http://angular-ui.github.io/ui-router/feature-1.0/ интерфейсы / 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);
});

Хотя такая работа для меня, мне пришлось ее настроить (также используя ES6)$transitions.onBefore({ to: state => state.defaultSubstate != null }, trans => trans.router.stateService.target(trans.to().defaultSubstate));
— yorch 01

3
app.config(function($stateProvider,$urlRouterProvider){

    $urlRouterProvider.when("/state","/state/sub-state");

    })

1
Можете ли вы объяснить, что это делает и почему это лучше, чем уже существующие ответы?
— Equalsk

Это самое простое решение, которое мне очень понравилось.
— BuffMcBigHuge

На сегодняшний день это лучший ответ. Более кратко, чем использование событий изменения. Не нужно добавлять пакеты. Не знаю, как это никому не понятно. Я не знаю, как за принятый ответ так проголосовали.
— CodeWarrior

1

Если кто-то придет сюда за ответом о том, как реализовать простое перенаправление для состояния и, как это случилось со мной, не имеет возможности использовать новый маршрутизатор ...

Очевидно, опять же, если вы можете, ответ @bblackwo отличный:

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

Если вы не можете, просто перенаправьте его вручную:

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

Я надеюсь, что это помогает!

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.