Come si naviga verso un percorso principale da un percorso figlio?


94

Il mio problema è abbastanza classico. Ho una parte privata di un'applicazione che si trova dietro a login form. Quando l'accesso ha esito positivo, passa a un percorso figlio per l'applicazione di amministrazione.

Il mio problema è che non posso usare global navigation menuperché il router cerca di instradare nel mio AdminComponentinvece che nel mio AppCompoment. Quindi la mia navigazione è interrotta.

Un altro problema è che se qualcuno vuole accedere direttamente all'URL, voglio reindirizzare alla route "login" genitore. Ma non riesco a farlo funzionare. Mi sembra che queste due questioni siano simili.

Qualche idea su come si può fare?


3
per favore aggiungi un codice
Jiang YD

Risposte:


157

Vuoi un link / HTML o vuoi instradare imperativamente / nel codice?

Collegamento : la direttiva RouterLink tratta sempre il collegamento fornito come un delta rispetto all'URL corrente:

[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"

Con RouterLink, ricordati di importare e utilizzare l' directivesarray:

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

Imperativo : il navigate()metodo richiede un punto di partenza (cioè il relativeToparametro). Se non viene fornito nessuno, la navigazione è assoluta:

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

1
il router.navigate(string)metodo non sembra esistere nella versione corrente di Angular (2.2). Ho cercato nei documenti e ho trovato solo navigate(commands: any[], extras?: NavigationExtras) : Promise<boolean>. O mi manca totalmente qualcosa?
Pomodoro

2
@Tomato, devi inserire [] nei percorsi. Ad esempio, this.router.navigate (["../../ parent"], {relativeTo: this.route});
gye

2
come si passano i relativeTodati quando si utilizza [routerLink] in html anziché in dattiloscritto?
redfox05

lo stesso con i servizi?
oCcSking

Per qualche motivo, nel mio caso devo usare ../../../invece di ../navigare verso genitore ( '/users'da '/users/1').
nelson6e65

50

Questo sembra funzionare per me a partire dalla primavera 2017:

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

Dove il tuo componente ctor accetta ActivatedRoutee Router, importato come segue:

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


4
Piuttosto che una data sarebbe più utile menzionare la versione angolare che stai usando.
isherwood

@isherwood Sono d'accordo. Scuse. Se ricordo bene, l'ho scritto per Angular 4.0.x ed era ancora funzionante in 4.3.x. Purtroppo ora mi sono allontanato da Angular,
ne1410s

@ ne1410s Grazie mille mancava il parente: this.route
Ian Samz

Nota: NON funzionerà con segmenti di router aggiuntivi su moduli con caricamento lento. EX:: parentPath'work: queue' (che ha figli) e ha detto che i bambini caricano il modulo figlio con i parametri. fullCurrentPath: "lavoro / spedizione / modulo / lista". Il codice precedente non può essere caricato parentPathda fullCurrentPath.
Don Thomas Boyle

34

Puoi navigare alla radice del tuo genitore in questo modo

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

Dovrai inserire il percorso attivo corrente nel costruttore

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

  }

2
Aggiungere qualche spiegazione renderebbe questa risposta più utile.
Sagar Zala

Molte persone suggeriscono di navigare su sibling con this.router.navigate (["../ sibling"], {relativeTo: this.route}); Tuttavia, questo non funziona più. Probabilmente ho trovato questa risposta funzionante. Invece di utilizzare "../" per passare a genitore. change relativeTo da this.route a this.route.parent è il modo corretto
Terry Lam,

1
@ChrisLamothe: Oh sì, ho commesso un errore. Funziona in generale. Tuttavia, non funziona nelle rotte ausiliarie. Ciò significa che this.router.navigate (['../ sibling']) funziona ma non this.router.navigate ([{outlets: {'secondary': ['../sibling']}}]). Nel routing ausiliario, devo usare this.router.navigate ([{outlets: {'secondary': ['sibling']}}], {relativeTo: this.activatedRoute.parent}).
Terry Lam

2
Inoltre, il metodo di navigazione da questa risposta this.router.navigate(['.'], {relativeTo: this.activeRoute.parent});funzionerà correttamente in un caso, quando utilizzi lo stesso componente in due percorsi: / users / create e / users / edit / 123. In entrambi i casi passerà a genitore / utenti. La normale navigazione con this.router.navigate([".."], {relativeTo: this.activeRoute})funzionerà solo per gli utenti / create ma non funzionerà per gli utenti / modifica / 123 perché navigherà verso / utenti / modifica / rotta non esistenti.
Roganik

1
+1 per un'alternativa ma personalmente, sono un po 'un byte chaser e investirei un punto in più nel parametro, [".."] , per eliminare il riferimento al genitore, {relativeTo: this.route} .
Konrad Viltersten

7
constructor(private router: Router) {}

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

Il router supporta

  • percorsi assoluti /xxx: avviati sul router del componente root
  • percorsi relativi xxx- avviati sul router del componente corrente
  • percorsi relativi ../xxx: avviati sul router principale del componente corrente

Sebbene questo codice possa rispondere alla domanda, fornire un contesto aggiuntivo sul perché e / o come risponde alla domanda ne migliorerebbe significativamente il valore a lungo termine. Si prega di modificare la risposta di aggiungere qualche spiegazione.
Toby Speight

1
@TobySpeight abbastanza giusto. Presumo ../sia conosciuto abbastanza bene, ma alla fine è ancora ambiguo. Grazie per il suggerimento.
Günter Zöchbauer

1
Grazie per la risposta, lavoro su questo sito da un po 'di tempo, quindi Angular è stato ovviamente aggiornato da allora. Ho provato questa soluzione nella mia versione attuale e non funziona. Fammi aggiornare e commenterò di nuovo dopo.
Carl Boisvert

1
Non riesco a far funzionare il tuo codice come previsto. Tuttavia, aggiungendo esplicitamente {relativeTo: this.route} come secondo parametro nella chiamata per navigare , funziona. Lo attribuirei a uno stupido errore di battitura se non fosse per il fatto che le tue risposte generalmente hanno un grado estremo di accuratezza. È forse un cambiamento nel comportamento del router da quando è stata fornita la risposta (3,6 anni fa, che negli anni di Angular è come un'eternità mezza eterna)?
Konrad Viltersten

Questa è una vecchia risposta e il router è cambiato molto in questo momento. Penso che la mia risposta sia obsoleta considerando che ci sono diverse risposte con più voti positivi. Non sto più facendo così tante cose dell'interfaccia utente web e non ho tutti i dettagli in cima alla mia testa.
Günter Zöchbauer

6

Per navigare al componente genitore indipendentemente dal numero di parametri nella rotta corrente o nella rotta genitore: Angular 6 update 1/21/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);

Questo ha il vantaggio di essere un percorso assoluto che puoi utilizzare con il router singleton.

(Angular 4+ di sicuro, probabilmente anche Angular 2.)


stranamente, questo restituisce sempre un array vuoto e ottiene lo stesso risultato di this._router.navigate([]), while this._router.navigate([[]])porta alla rotta genitore, se e solo se la rotta genitore non è root stessa.
Ashish Jhanwar

codice aggiornato per riflettere le modifiche di Angular 6 e la corretta ricerca genitore con genitori e figli che contengono figli nelle rotte.
Don Thomas Boyle

Sei sicuro che non sia qualcosa di specifico per il tuo caso d'uso? Sembrerebbe che non aggiungere l'ultimo percorso trasformerebbe ['orders', '123', 'items', 1] solo in ['orders'], il che non sembra affatto corretto. In ogni caso, siamo passati da Angular 5 a 7 e non abbiamo toccato questo codice.
kayjtea

sono il numero di div sulla mia pagina .. al clic di ogni div passo la query parms e carico un componente. ora usando il pulsante Indietro del browser voglio tornare indietro come fare?
Vrajendra Singh Mandloi

4

Un altro modo potrebbe essere così

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

ed ecco il costruttore

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

4

senza molto rumore:

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

il parametro ".." fa salire di livello la navigazione, ovvero genitore :)


Potresti menzionare lo scopo / la necessità di skipLocationChange .
Konrad Viltersten

1

I miei percorsi hanno uno schema come questo:

  • utente / modifica / 1 -> Modifica
  • utente / crea / 0 -> Crea
  • utente / -> Elenco

Quando sono nella pagina Modifica, ad esempio, e devo tornare alla pagina dell'elenco, tornerò di 2 livelli in alto sul percorso.

Pensando a questo, ho creato il mio metodo con un parametro "level".

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

Quindi, per passare dalla modifica all'elenco chiamo il metodo in questo modo:

this.goBack(2);

0

Se stai usando la direttiva uiSref, puoi farlo

uiSref="^"

0

La mia soluzione è:

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

E l' Routeriniezione:

private readonly _router: Router

0

Niente di tutto questo ha funzionato per me ... ho dovuto usare:

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

private router: Router

this.router.navigate([this.router.url.substring(0, this.router.url.lastIndexOf('/'))]);

Aggiorna la tua risposta con una descrizione del motivo per cui funziona. Si prega di vedere come rispondere .
Gerald Zehetner

-2

aggiungi Location al tuo costruttore da @angular/common

constructor(private _location: Location) {}

aggiungi la funzione back:

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

e poi a tuo avviso:

<button class="btn" (click)="back()">Back</button>

5
Funziona solo se in precedenza eri nel percorso principale. I percorsi dei genitori non hanno nulla a che fare con la cronologia del browser ...
leviathanbadger

torna indietro, ma non torna al genitore del componente
Andrew Andreev

Questo non dovrebbe essere usato, se l'utente accede al componente da un sito esterno, verrebbe reindirizzato a quel sito. Questo codice
equivale
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.