Jak nawigować do trasy nadrzędnej z trasy podrzędnej?

89

Mój problem jest dość klasyczny. Mam prywatną część aplikacji, która znajduje się za plikiem login form. Po pomyślnym zalogowaniu następuje przejście do trasy podrzędnej dla aplikacji administratora.

Mój problem polega na tym, że nie mogę użyć, global navigation menuponieważ router próbuje trasować w moim AdminComponentzamiast moim AppCompoment. Więc moja nawigacja jest zepsuta.

Innym problemem jest to, że jeśli ktoś chce uzyskać bezpośredni dostęp do adresu URL, chcę przekierować do nadrzędnej trasy „logowania”. Ale nie mogę sprawić, żeby to zadziałało. Wydaje mi się, że te dwie kwestie są podobne.

Masz jakiś pomysł, jak to zrobić?

Carl Boisvert
źródło
3
proszę dodać kod
Jiang YD

Odpowiedzi:

153

Czy chcesz link / HTML, czy chcesz kierować bezwzględnie / w kodzie?

Link : Dyrektywa RouterLink zawsze traktuje podane łącze jako różnicę do bieżącego adresu URL:

[routerLink]="['/absolute']"
[routerLink]="['../../parent']"
[routerLink]="['../sibling']"
[routerLink]="['./child']"     // or
[routerLink]="['child']" 

// with route param     ../../parent;abc=xyz
[routerLink]="['../../parent', {abc: 'xyz'}]"
// with query param and fragment   ../../parent?p1=value1&p2=v2#frag
[routerLink]="['../../parent']" [queryParams]="{p1: 'value', p2: 'v2'}" fragment="frag"

W przypadku RouterLink pamiętaj, aby zaimportować i używać directivestablicy:

import { ROUTER_DIRECTIVES } from '@angular/router';
@Component({
    directives: [ROUTER_DIRECTIVES],

Tryb konieczny : navigate()metoda wymaga punktu początkowego (tj. relativeToParametru). Jeśli nie podano, nawigacja jest bezwzględna:

import { Router, ActivatedRoute } from '@angular/router';
...
constructor(private router: Router, private route: ActivatedRoute) {}
...
this.router.navigate(["/absolute/path"]);
this.router.navigate(["../../parent"], {relativeTo: this.route});
this.router.navigate(["../sibling"],   {relativeTo: this.route});
this.router.navigate(["./child"],      {relativeTo: this.route}); // or
this.router.navigate(["child"],        {relativeTo: this.route});

// with route param     ../../parent;abc=xyz
this.router.navigate(["../../parent", {abc: 'xyz'}], {relativeTo: this.route});
// with query param and fragment   ../../parent?p1=value1&p2=v2#frag
this.router.navigate(["../../parent"], {relativeTo: this.route, 
    queryParams: {p1: 'value', p2: 'v2'}, fragment: 'frag'});

// navigate without updating the URL 
this.router.navigate(["../../parent"], {relativeTo: this.route, skipLocationChange: true});
Mark Rajcok
źródło
1
router.navigate(string)metoda nie wydaje się istnieć w obecnej wersji kątowej (2.2). Szukałem w dokumentach i tylko znalazłem navigate(commands: any[], extras?: NavigationExtras) : Promise<boolean>. A może całkowicie czegoś mi brakuje?
Pomidor
2
@Tomato, musisz umieścić [] wokół tras. Na przykład this.router.navigate (["../../ parent"], {relativeTo: this.route});
gye
2
Jak przekazać relativeTodane, gdy używasz [routerLink] w html zamiast maszynopisu?
redfox05
to samo z usługami?
oCcSking
Z jakiegoś powodu w moim przypadku muszę użyć ../../../zamiast ../nawigować do rodzica ( '/users'z '/users/1').
nelson6e65
47

To wydaje się działać dla mnie od wiosny 2017 r .:

goBack(): void {
  this.router.navigate(['../'], { relativeTo: this.route });
}

Tam, gdzie Twój komponent akceptuje ActivatedRoutei Routerimportuje w następujący sposób:

import { ActivatedRoute, Router } from '@angular/router';

ne1410s
źródło
4
Zamiast daty, bardziej przydatne byłoby wspomnienie o wersji Angulara, której używasz.
isherwood,
@isherwood Zgadzam się. Przeprosiny. Jeśli dobrze pamiętam, napisałem go dla Angulara 4.0.x i nadal działał w 4.3.x. Niestety teraz wyprowadziłem się z
Angulara
@ ne1410s dziękuję brakowało względna: this.route
Ian Samz
Uwaga: NIE będzie działać z dodatkowymi segmentami routera w modułach ładowanych z opóźnieniem. EX:: parentPath'work: queue' (który ma dzieci) i wspomniane dzieci ładują moduł potomny z parametrami. fullCurrentPath: „praca / wysyłka / moduł / lista”. Powyższego kodu nie można załadować parentPathz fullCurrentPath.
Don Thomas Boyle
32

W ten sposób możesz przejść do głównego katalogu głównego

this.router.navigate(['.'], { relativeTo: this.activeRoute.parent });

Będziesz musiał wstrzyknąć bieżącą aktywną trasę do konstruktora

constructor(
    private router: Router,
    private activeRoute: ActivatedRoute) {

  }
Chris Lamothe
źródło
2
Dodanie jakiegoś wyjaśnienia uczyniłoby tę odpowiedź bardziej użyteczną.
Sagar Zala
Wiele osób sugeruje nawigację do rodzeństwa przez this.router.navigate (["../ sibling"], {relativeTo: this.route}); Jednak to już nie działa. Uważam, że ta odpowiedź prawdopodobnie działa. Zamiast używać „../” do nawigacji do rodzica. zmień względną na to z this.route na this.route.parent to właściwa droga
Terry Lam
1
@ChrisLamothe: O tak, popełniłem błąd. Działa w ogólnym przypadku. Jednak nie działa na trasach pomocniczych. Oznacza to, że this.router.navigate (['../ sibling']) działa, ale nie this.router.navigate ([{outlets: {'secondary': ['../sibling']}}]). W routingu pomocniczym muszę użyć this.router.navigate ([{outlets: {'secondary': ['sibling']}}], {relativeTo: this.activatedRoute.parent}).
Terry Lam
2
Również sposób nawigacji z tej odpowiedzi this.router.navigate(['.'], {relativeTo: this.activeRoute.parent});będzie działał poprawnie w przypadku, gdy użyjesz tego samego komponentu w dwóch ścieżkach: / users / create i / users / edit / 123. W obu przypadkach przejdzie do rodzica / użytkowników. Zwykła nawigacja this.router.navigate([".."], {relativeTo: this.activeRoute})będzie działać tylko dla użytkowników / create, ale nie będzie działać dla użytkowników / edit / 123, ponieważ będzie nawigować do nieistniejących / users / edit / route.
Roganik
1
+1 dla alternatywy, ale osobiście jestem trochę łowcą bajtów i zainwestowałbym dodatkową kropkę w parametr [".."] , aby wyeliminować odniesienie do rodzica, {relativeTo: this.route} .
Konrad Viltersten
7
constructor(private router: Router) {}

navigateOnParent() {
  this.router.navigate(['../some-path-on-parent']);
}

Router obsługuje

  • ścieżki bezwzględne /xxx- uruchamiane na routerze komponentu głównego
  • ścieżki względne xxx- uruchamiane na routerze bieżącego komponentu
  • ścieżki względne ../xxx- rozpoczęte na routerze nadrzędnym bieżącego komponentu
Günter Zöchbauer
źródło
Chociaż ten kod może odpowiedzieć na pytanie, dostarczenie dodatkowego kontekstu dotyczącego tego, dlaczego i / lub jak odpowiada na pytanie, znacznie poprawiłoby jego długoterminową wartość. Proszę edytować swoje odpowiedzi, aby dodać trochę wyjaśnień.
Toby Speight
1
@TobySpeight Fair wystarczająco. Zakładałem, że ../jest wystarczająco dobrze znany, ale ostatecznie jest to nadal niejednoznaczne. Dzięki za podpowiedź.
Günter Zöchbauer
1
Dzięki za odpowiedź, nad tą stroną pracuję już od jakiegoś czasu, więc Angular jak oczywiście został zaktualizowany. Wypróbowałem to rozwiązanie w mojej obecnej wersji i nie działa. Zaktualizuję, a później skomentuję.
Carl Boisvert
1
Twój kod nie działa zgodnie z oczekiwaniami. Jednak po jawnym dodaniu {względnaTo: this.route} jako drugi parametr w wywołaniu nawigacji działa. Określiłbym to jako głupią literówkę, gdyby nie fakt, że twoje odpowiedzi mają generalnie skrajny stopień dokładności. Czy to może zmiana w zachowaniu routera od czasu udzielenia odpowiedzi (3,6 roku temu, co w latach Angulara jest jak półkolista wieczność)?
Konrad Viltersten
To stara odpowiedź, a router bardzo się zmienił w tym czasie. Myślę, że moja odpowiedź jest po prostu nieaktualna, biorąc pod uwagę, że jest kilka odpowiedzi z większą liczbą głosów pozytywnych. Nie robię już tyle rzeczy z interfejsem WWW i nie mam wszystkich szczegółów na głowie.
Günter Zöchbauer
6

Aby nawigować do komponentu nadrzędnego niezależnie od liczby parametrów w bieżącej trasie lub trasie nadrzędnej: Angular 6 aktualizacja 21.01.2019

   let routerLink = this._aRoute.parent.snapshot.pathFromRoot
        .map((s) => s.url)
        .reduce((a, e) => {
            //Do NOT add last path!
            if (a.length + e.length !== this._aRoute.parent.snapshot.pathFromRoot.length) {
                return a.concat(e);
            }
            return a;
        })
        .map((s) => s.path);
    this._router.navigate(routerLink);

Ma to dodatkową zaletę, że jest trasą absolutną, której można używać z pojedynczym routerem.

(Na pewno Angular 4+, prawdopodobnie też Angular 2.)

kayjtea
źródło
co dziwne, to zawsze zwraca pustą tablicę i osiąga ten sam wynik, co this._router.navigate([]), while this._router.navigate([[]])zabiera do trasy nadrzędnej wtedy i tylko wtedy, gdy trasa nadrzędna nie jest sama w sobie rootem.
Ashish Jhanwar,
zaktualizowany kod, aby odzwierciedlić zmiany w Angular 6 i prawidłowe wyszukiwanie rodzica z rodzicem i dzieckiem zawierającym dzieci w trasach.
Don Thomas Boyle
Czy na pewno nie jest to coś konkretnego dla Twojego przypadku użycia? Wydawałoby się, że nie dołączenie ostatniej ścieżki zmieniłoby [„zamówienia”, „123”, „przedmioty”, 1] ​​w tylko [„zamówienia”], co wcale nie wydaje się właściwe. W każdym razie przeszliśmy z Angular 5 do 7 i nie dotykaliśmy tego zakodowanego.
kayjtea
ich liczba div na mojej stronie .. po kliknięciu każdego div przekazuję parametry zapytania i ładuję komponent. teraz używając przycisku Wstecz w przeglądarce, chcę wrócić, jak to zrobić?
Vrajendra Singh Mandloi
4

Inny sposób mógłby wyglądać tak

this._router.navigateByUrl(this._router.url.substr(0, this._router.url.lastIndexOf('/'))); // go to parent URL

a oto konstruktor

constructor(
    private _activatedRoute: ActivatedRoute,
    private _router: Router
  ) { }
Johansrk
źródło
3

bez zbędnych ceregieli:

this.router.navigate(['..'], {relativeTo: this.activeRoute, skipLocationChange: true});

parametr '..' sprawia , że nawigacja jest o jeden poziom wyżej, czyli rodzic :)

Igor Zinin
źródło
Możesz wspomnieć o celu / potrzebie skipLocationChange .
Konrad Viltersten
1

Moje trasy mają następujący wzór:

  • użytkownik / edit / 1 -> Edit
  • user / create / 0 -> Create
  • użytkownik / -> Lista

Na przykład, gdy jestem na stronie edycji i muszę wrócić do strony z listą, wrócę o 2 poziomy wyżej na trasie.

Myśląc o tym, stworzyłem moją metodę z parametrem „level”.

goBack(level: number = 1) {
    let commands = '../';
    this.router.navigate([commands.repeat(level)], { relativeTo: this.route });
}

Aby przejść od edycji do listy, wywołuję tę metodę:

this.goBack(2);
Carlinhos
źródło
0

dodaj lokalizację do konstruktora z @angular/common

constructor(private _location: Location) {}

dodaj funkcję wstecz:

back() {
  this._location.back();
}

a następnie Twoim zdaniem:

<button class="btn" (click)="back()">Back</button>
user3021615
źródło
5
Działa to tylko wtedy, gdy wcześniej byłeś na trasie nadrzędnej. Trasy rodzicielskie nie mają nic wspólnego z historią przeglądarki ...
leviathanbadger
przechodzi wstecz, ale nie przechodzi do nadrzędnego komponentu
Andrew Andreev,
Nie należy tego używać, jeśli użytkownik przejdzie do komponentu z zewnętrznej witryny, zostanie on przeniesiony z powrotem do tej witryny. Ten kod jest taki sam, jak kliknięcie PRZYCISKU WSTECZ W PRZEGLĄDARCE
T04435,
0

Jeśli używasz dyrektywy uiSref, możesz to zrobić

uiSref="^"
Zuriel
źródło
0

Moje rozwiązanie to:

const urlSplit = this._router.url.split('/');
this._router.navigate([urlSplit.splice(0, urlSplit.length - 1).join('/')], { relativeTo: this._route.parent });

I Routerwtrysk:

private readonly _router: Router
anlijudavid
źródło