Перенаправить состояние в подсостояние по умолчанию с помощью 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' } },
  });

Спасибо!

Лео
источник
12

Начиная с версии 1.0 ui-router он поддерживает redirectToсвойство. Например:

.state('A', {
  redirectTo: 'A.B'
})
BBlackwo
источник
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);
});
ThmX
источник
Хотя такая работа для меня, мне пришлось ее настроить (также используя 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');
  },
});

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

Хосе Даниэль Вивар Персонат
источник