Wie navigiere ich von einer untergeordneten Route zu einer übergeordneten Route?

85

Mein Problem ist ziemlich klassisch. Ich habe einen privaten Teil einer Anwendung, der hinter a steht login form. Wenn die Anmeldung erfolgreich ist, wird eine untergeordnete Route für die Administratoranwendung aufgerufen.

Mein Problem ist, dass ich das nicht verwenden kann, global navigation menuweil der Router versucht, in meinem AdminComponentstatt in meinem zu routen AppCompoment. Meine Navigation ist also kaputt.

Ein weiteres Problem ist, dass ich, wenn jemand direkt auf die URL zugreifen möchte, zur übergeordneten "Anmelderoute" umleiten möchte. Aber ich kann es nicht zum Laufen bringen. Mir scheint, dass diese beiden Themen ähnlich sind.

Irgendeine Idee, wie es gemacht werden kann?

Carl Boisvert
quelle
3
Bitte fügen Sie einen Code hinzu
Jiang YD

Antworten:

147

Möchten Sie einen Link / HTML oder möchten Sie zwingend / in Code routen?

Link : Die RouterLink-Direktive behandelt den bereitgestellten Link immer als Delta zur aktuellen 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"

Denken Sie bei RouterLink daran, das directivesArray zu importieren und zu verwenden :

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

Imperativ : Die navigate()Methode erfordert einen Startpunkt (dh den relativeToParameter). Wenn keine angegeben ist, ist die Navigation absolut:

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
quelle
1
Die router.navigate(string)Methode scheint in der aktuellen Version von Angular (2.2) nicht zu existieren. Ich habe in den Dokumenten gesucht und nur gefunden navigate(commands: any[], extras?: NavigationExtras) : Promise<boolean>. Oder fehlt mir etwas total?
Tomate
2
@ Tomate, müssen Sie [] um die Routen setzen. Zum Beispiel this.router.navigate (["../../ parent"], {relativeTo: this.route});
Gye
2
Wie übergeben Sie die relativeToDaten, wenn Sie [routerLink] im HTML-Code anstelle von Typoskript verwenden?
Redfox05
das gleiche mit Dienstleistungen?
OKCSking
47

Dies scheint für mich ab Frühjahr 2017 zu funktionieren:

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

Wo Ihre Komponente ctor akzeptiert ActivatedRouteund Routerwie folgt importiert:

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

ne1410s
quelle
4
Anstelle eines Datums wäre es sinnvoller, die Angular-Version zu erwähnen, die Sie gerade verwenden.
Isherwood
@isherwood Ich stimme zu. Entschuldigung. Wenn ich mich richtig erinnere, habe ich es für Angular 4.0.x geschrieben und es war in 4.3.x immer noch funktionsfähig. Leider bin ich jetzt von Angular
weggezogen
@ ne1410s Vielen Dank fehlte der Verwandte: this.route
Ian Samz
Hinweis: Funktioniert NICHT mit zusätzlichen Routersegmenten auf träge geladenen Modulen. EX :: parentPath'work: queue' (mit Kindern) und die Kinder laden das Kindermodul mit Parametern. fullCurrentPath: 'Arbeit / Versand / Modul / Liste'. Der obige Code kann nicht geladen parentPathaus fullCurrentPath.
Don Thomas Boyle
31

Sie können so zu Ihrem übergeordneten Stamm navigieren

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

Sie müssen die aktuell aktive Route in den Konstruktor einfügen

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

  }
Chris Lamothe
quelle
2
Das Hinzufügen einer Erklärung würde diese Antwort nützlicher machen.
Sagar Zala
Viele Leute schlagen vor, mit this.router.navigate (["../ sibling"], {relativeTo: this.route}) zum Geschwister zu navigieren. Dies funktioniert jedoch nicht mehr. Ich fand diese Antwort wahrscheinlich. Anstatt '../' zu verwenden, um zum übergeordneten Element zu navigieren. Ändern Sie relativeTo von this.route zu this.route.parent ist der richtige Weg
Terry Lam
1
@ ChrisLamothe: Oh ja, ich habe einen Fehler gemacht. Es funktioniert im Allgemeinen. Es funktioniert jedoch nicht auf Hilfsrouten. Das bedeutet, dass this.router.navigate (['../ sibling']) funktioniert, aber nicht this.router.navigate ([{outlet: {'Secondary': ['../sibling']}}). Beim Auxiliary Routing muss ich this.router.navigate verwenden ([{outlet: {'primary': ['sibling']}}], {relativeTo: this.activatedRoute.parent}).
Terry Lam
2
Außerdem this.router.navigate(['.'], {relativeTo: this.activeRoute.parent});funktioniert die Navigationsmethode aus dieser Antwort in einem Fall ordnungsgemäß, wenn Sie dieselbe Komponente in zwei Pfaden verwenden: / users / create und / users / edit / 123. In beiden Fällen wird zu Eltern / Benutzern navigiert. Die reguläre Navigation mit this.router.navigate([".."], {relativeTo: this.activeRoute})funktioniert nur für die Benutzer / create, aber nicht für die Benutzer / edit / 123, da sie zu nicht vorhandenen / users / edit / route navigiert.
Roganik
1
+1 für eine Alternative, aber persönlich bin ich ein bisschen ein Byte-Chaser und würde einen zusätzlichen Punkt in den Parameter [".."] investieren , um den Verweis auf das übergeordnete Element {relativeTo: this.route} zu eliminieren .
Konrad Viltersten
7
constructor(private router: Router) {}

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

Der Router unterstützt

  • absolute Pfade /xxx- gestartet auf dem Router der Root-Komponente
  • relative Pfade xxx- gestartet auf dem Router der aktuellen Komponente
  • relative Pfade ../xxx- gestartet auf dem übergeordneten Router der aktuellen Komponente
Günter Zöchbauer
quelle
Obwohl dieser Code die Frage möglicherweise beantwortet, würde die Bereitstellung eines zusätzlichen Kontexts darüber, warum und / oder wie er die Frage beantwortet, ihren langfristigen Wert erheblich verbessern. Bitte bearbeiten Sie Ihre Antwort, um eine Erklärung hinzuzufügen.
Toby Speight
1
@ TobySpeight Fair genug. Ich nahm an, dass ../es gut genug bekannt ist, aber am Ende ist es immer noch mehrdeutig. Danke für den Tipp.
Günter Zöchbauer
1
Vielen Dank für die Antwort, ich arbeite schon seit einiger Zeit an dieser Website, daher wurde Angular offensichtlich seitdem aktualisiert. Ich habe diese Lösung in meiner aktuellen Version ausprobiert und sie funktioniert nicht. Lassen Sie mich aktualisieren und ich werde danach kommentieren.
Carl Boisvert
1
Ich bekomme Ihren Code nicht wie erwartet zum Laufen. Durch explizites Hinzufügen von {relativeTo: this.route} als zweitem Parameter im Aufruf zur Navigation funktioniert dies jedoch. Ich würde es zu einem dummen Tippfehler machen, wenn nicht die Tatsache gewesen wäre, dass Ihre Antworten im Allgemeinen ein extremes Maß an Genauigkeit aufweisen. Ist es vielleicht eine Änderung des Verhaltens des Routers seit der Antwort (vor 3,6 Jahren, was in Angular-Jahren wie eine halbe Ewigkeit ist)?
Konrad Viltersten
Dies ist eine alte Antwort und der Router hat sich zu diesem Zeitpunkt stark verändert. Ich denke, meine Antwort ist nur veraltet, wenn man bedenkt, dass es mehrere Antworten mit mehr positiven Stimmen gibt. Ich mache nicht mehr so ​​viel Web-UI-Zeug und habe nicht alle Details auf dem Kopf.
Günter Zöchbauer
6

So navigieren Sie zur übergeordneten Komponente, unabhängig von der Anzahl der Parameter in der aktuellen Route oder der übergeordneten Route: Angular 6-Update 21.01.19

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

Dies hat den zusätzlichen Vorteil, dass es sich um eine absolute Route handelt, die Sie mit dem Singleton-Router verwenden können.

(Angular 4+ sicher, wahrscheinlich auch Angular 2.)

Kayjtea
quelle
Seltsamerweise gibt dies immer ein leeres Array zurück und erzielt das gleiche Ergebnis wie this._router.navigate([])beim this._router.navigate([[]])Übernehmen der übergeordneten Route, wenn und nur wenn die übergeordnete Route selbst nicht root ist.
Ashish Jhanwar
Der Code wurde aktualisiert, um Änderungen in Winkel 6 und die ordnungsgemäße Suche der Eltern mit Eltern und Kindern, die Kinder in Routen enthalten, widerzuspiegeln.
Don Thomas Boyle
Sind Sie sicher, dass dies nicht spezifisch für Ihren Anwendungsfall ist? Es scheint, als würde das Nichtanhängen des letzten Pfades ['Bestellungen', '123', 'Artikel', 1] in nur ['Bestellungen'] verwandeln, was überhaupt nicht richtig zu sein scheint. Auf jeden Fall sind wir einfach von Angular 5 auf 7 gegangen und haben diesen Code nicht berührt.
Kayjtea
Es gibt die Anzahl der Divs auf meiner Seite. Beim Klicken auf jedes Div übergebe ich Abfrageparameter und lade eine Komponente. Jetzt mit dem Browser-Zurück-Button möchte ich zurückgehen, wie das geht?
Vrajendra Singh Mandloi
4

Ein anderer Weg könnte so sein

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

und hier ist der Konstruktor

constructor(
    private _activatedRoute: ActivatedRoute,
    private _router: Router
  ) { }
Johansrk
quelle
3

ohne viel Aufhebens:

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

Parameter '..' macht die Navigation eine Ebene höher, dh Eltern :)

Igor Zinin
quelle
Vielleicht möchten Sie den Zweck / die Notwendigkeit von skipLocationChange erwähnen .
Konrad Viltersten
1

Meine Routen haben ein Muster wie das folgende:

  • Benutzer / bearbeiten / 1 -> Bearbeiten
  • user / create / 0 -> Erstellen
  • Benutzer / -> Liste

Wenn ich zum Beispiel auf der Seite Bearbeiten bin und zur Listenseite zurückkehren muss, gebe ich 2 Ebenen auf der Route zurück.

Als ich darüber nachdachte, erstellte ich meine Methode mit einem "Level" -Parameter.

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

Um von der Bearbeitung zur Liste zu gelangen, rufe ich die Methode folgendermaßen auf:

this.goBack(2);
Carlinhos
quelle
0

Fügen Sie Ihrem Konstruktor den Speicherort von hinzu @angular/common

constructor(private _location: Location) {}

Fügen Sie die Rückfunktion hinzu:

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

und dann aus Ihrer Sicht:

<button class="btn" (click)="back()">Back</button>
user3021615
quelle
5
Dies funktioniert nur, wenn Sie sich zuvor in der übergeordneten Route befanden. Übergeordnete Routen haben nichts mit dem Browserverlauf zu tun ...
Leviathanbadger
es navigiert zurück, aber nicht zum übergeordneten Element der Komponente
Andrew Andreev
Dies sollte nicht verwendet werden. Wenn der Benutzer von einer externen Site zu der Komponente wechselt, wird sie zu dieser Site zurückgeführt. Dieser Code ist der gleiche wie das Klicken auf die Schaltfläche ZURÜCK IM BROWSER
T04435
0

Wenn Sie die uiSref-Direktive verwenden, können Sie dies tun

uiSref="^"
Zuriel
quelle
0

Meine Lösung ist:

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

Und die RouterInjektion:

private readonly _router: Router
anlijudavid
quelle