Przekieruj stan do domyślnego podstatu za pomocą UI-Router w AngularJS

89

Tworzę stronę opartą na kartach, która pokazuje pewne dane. Używam UI-Router w AngularJs do rejestrowania stanów.

Moim celem jest otwarcie jednej domyślnej karty podczas ładowania strony. Każda karta ma zakładki podrzędne i chciałbym, aby domyślna karta podrzędna była otwarta podczas zmiany zakładek.

Testowałem z onEnterfunkcją i używam wewnątrz, $state.go('mainstate.substate');ale wydaje się, że nie działa z powodu problemów z efektem pętli (w przypadku state.go podstate wywołuje stan nadrzędny i tak dalej, i zamienia się w pętlę).

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

Tutaj stworzyłem demo plunkera .

Na razie wszystko działa, z wyjątkiem tego, że nie mam otwartej domyślnej karty i właśnie tego potrzebuję.

Dziękuję za sugestie, opinie i pomysły.

Lew
źródło

Odpowiedzi:

172

Aktualizacja: od wersji 1.0 Obsługuje przekierowanie po wyjęciu z pudełka.

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


Stworzyłem tutaj przykład .

To rozwiązanie pochodzi od miłego „komentarza” do problemu z przekierowaniem przy użyciu .when() ( https://stackoverflow.com/a/27131114/1679310 ) i naprawdę fajnego rozwiązania (autorstwa Chrisa T, ale oryginalny post był przez yahyaKacem)

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

Więc najpierw rozszerzmy main o ustawienie przekierowania:

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

I dodaj tylko te kilka wierszy do uruchomienia

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

W ten sposób możemy dostosować dowolny z naszych stanów z domyślnym przekierowaniem ... Sprawdź to tutaj

EDYCJA: Dodano opcję z komentarza @Alec, aby zachować historię przeglądarki.

Radim Köhler
źródło
4
Wydaje się, że wbija się w przycisk Wstecz.
Scott Sword
6
@ Swordfish0321, aby naprawić przycisk Wstecz, wprowadź tę małą zmianę: $state.go(to.redirectTo, params, {location: 'replace'});spowoduje to, że nowy stan zastąpi poprzedni stan (tj. Ten, z którego jesteśmy przekierowywani) w historii. Zobacz dokumentację $ state.go: angular-ui.github.io/ui-router/site/#/api/…
Alec
2
Chciałem tylko dodać, że było to naprawdę bliskie temu, co chciałem zrobić, ale chciałem domyślnego adresu URL zamiast go zastępować, można to łatwo osiągnąć, zmieniając '$stateChangeStart'na'$stateChangeSuccess'
Matti Price
6
ui-router 1.0 ma wbudowaną obsługę tego: ui-router.github.io/guide/ng1/…
Gert-Jan
21

W rzeczywistości nawet jeśli to rozwiązanie zaproponowane przez Radima wykonało dokładnie swoją pracę, musiałem zapamiętać zakładkę podrzędną (stan) każdej zakładki.

Znalazłem więc inne rozwiązanie, które robi to samo, ale również pamięta każdy podstat karty.

Wszystko, co musiałem zrobić, to zainstalować dodatki ui-routera i użyć funkcji przekierowania głębokiego stanu :

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

Dziękuję Ci!

Lew
źródło
12

Od wersji 1.0 routera ui obsługuje redirectTowłaściwość. Na przykład:

.state('A', {
  redirectTo: 'A.B'
})
BBlackwo
źródło
7

Od wersji 1.0 ui-routera, domyślny punkt zaczepienia został wprowadzony przy użyciu IHookRegistry.onBefore (), jak pokazano w przykładzie Data Driven Default Substate w http://angular-ui.github.io/ui-router/feature-1.0/ interfaces / transit.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
źródło
Ten rodzaj pracy dla mnie, chociaż musiałem to poprawić (również używając ES6)$transitions.onBefore({ to: state => state.defaultSubstate != null }, trans => trans.router.stateService.target(trans.to().defaultSubstate));
yorch
3
app.config(function($stateProvider,$urlRouterProvider){

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

    })
shubam yadav
źródło
1
Czy możesz wyjaśnić, co to robi i dlaczego jest lepsze niż już istniejące odpowiedzi?
Equalsk
To rozwiązanie jest najłatwiejsze i dobrze się sprawdziło.
BuffMcBigHuge
To zdecydowanie najlepsza odpowiedź. Bardziej zwięzłe niż używanie zdarzeń zmian. Nie ma potrzeby dodawania pakietów. Nie wiem, jak to dla nikogo nie jest jasne. Nie wiem, w jaki sposób przyjęta odpowiedź została tak bardzo pozytywnie oceniona.
CodeWarrior
1

Jeśli ktoś przychodzi tu po odpowiedź jak zaimplementować proste przekierowanie na stan i jak mi się przydarzyło nie ma możliwości skorzystania z nowego routera ...

Oczywiście ponownie, jeśli możesz, odpowiedź @bblackwo jest świetna:

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

Jeśli nie możesz, po prostu ręcznie przekieruj go:

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

Mam nadzieję, że to pomoże!

Jose Daniel Vivar Personat
źródło