¿Cómo navego a una ruta principal desde una ruta secundaria?

89

Mi problema es bastante clásico. Tengo una parte privada de una aplicación que está detrás de un login form. Cuando el inicio de sesión es exitoso, se dirige a una ruta secundaria para la aplicación de administración.

Mi problema es que no puedo usar el global navigation menuporque el enrutador intenta enrutar mi en AdminComponentlugar de mi AppCompoment. Entonces mi navegación está rota.

Otro problema es que si alguien quiere acceder a la URL directamente, quiero redirigir a la ruta de "inicio de sesión" principal. Pero no puedo hacer que funcione. Me parece que estas dos cuestiones son similares.

¿Alguna idea de cómo se puede hacer?

Carl Boisvert
fuente
3
por favor agregue algún código
Jiang YD

Respuestas:

153

¿Quieres un enlace / HTML o quieres enrutar imperativamente / en código?

Enlace : la directiva RouterLink siempre trata el enlace proporcionado como un delta a la URL actual:

[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, recuerde importar y usar la directivesmatriz:

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

Imperativo : el navigate()método requiere un punto de partida (es decir, el relativeToparámetro). Si no se proporciona ninguno, la navegación es absoluta:

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
fuente
1
el router.navigate(string)método no parece existir en la versión actual de Angular (2.2). Busqué en los documentos y solo encontré navigate(commands: any[], extras?: NavigationExtras) : Promise<boolean>. ¿O me estoy perdiendo algo por completo?
Tomate
2
@Tomato, necesitas poner [] alrededor de las rutas. Por ejemplo, this.router.navigate (["../../ parent"], {relatedTo: this.route});
gye
2
¿Cómo se pasan los relativeTodatos cuando se usa [routerLink] en html en lugar de mecanografiado?
redfox05
lo mismo con los servicios?
oCcSking
Por alguna razón, en mi caso, tengo que usar en ../../../lugar de ../navegar a parent ( '/users'from '/users/1').
nelson6e65
47

Esto parece funcionar para mí a partir de la primavera de 2017:

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

Donde su componente ctor acepta ActivatedRoutee Routerimporta de la siguiente manera:

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

ne1410s
fuente
4
En lugar de una fecha, sería más útil mencionar la versión angular que está utilizando.
isherwood
@isherwood estoy de acuerdo. Disculpas Si mal no recuerdo, lo escribí para Angular 4.0.xy seguía funcionando en 4.3.x. Por desgracia he alejado del angular ahora,
ne1410s
@ ne1410s Gracias, faltaba mucho el familiar: this.route
Ian Samz
Nota: NO funcionará con segmentos de enrutador adicionales en módulos de carga diferida. EJ:: parentPath'trabajo: cola' (que tiene hijos) y dijo que los hijos cargan el módulo hijo con parámetros. fullCurrentPath: 'trabajo / envío / módulo / lista'. El código anterior no se puede cargar parentPathdesde fullCurrentPath.
Don Thomas Boyle
32

Puede navegar a su raíz principal de esta manera

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

Deberá inyectar la ruta activa actual en el constructor

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

  }
Chris Lamothe
fuente
2
Agregar alguna explicación haría que esta respuesta sea más útil.
Sagar Zala
Mucha gente sugiere navegar hasta el hermano por this.router.navigate (["../ sibling"], {relatedTo: this.route}); Sin embargo, esto ya no funciona. Encontré que esta respuesta funciona probablemente. En lugar de usar '../' para navegar a parent. cambiar relativoTo de this.route a this.route.parent es la forma correcta
Terry Lam
1
@ChrisLamothe: Oh, sí, cometí un error. Funciona en caso general. Sin embargo, no funciona en rutas auxiliares. Eso significa que this.router.navigate (['../ sibling']) está funcionando pero no this.router.navigate ([{outlets: {'secundario': ['../sibling']}}]). En el enrutamiento auxiliar, tengo que usar this.router.navigate ([{outlets: {'secundario': ['hermano']}}], {relativo a: this.activatedRoute.parent}).
Terry Lam
2
Además, el método de navegación de esta respuesta this.router.navigate(['.'], {relativeTo: this.activeRoute.parent});funcionará correctamente en un caso, cuando use el mismo componente en dos rutas: / users / create y / users / edit / 123. En ambos casos, navegará a padres / usuarios. La navegación normal con this.router.navigate([".."], {relativeTo: this.activeRoute})funcionará solo para los usuarios / crear, pero no funcionará para los usuarios / editar / 123 porque navegará a no existente / usuarios / editar / ruta.
Roganik
1
+1 para una alternativa, pero personalmente, soy un poco cazador de bytes e invertiría un punto extra en el parámetro, [".."] , para eliminar la referencia al padre, {relatedTo: this.route} .
Konrad Viltersten
7
constructor(private router: Router) {}

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

El enrutador admite

  • rutas absolutas /xxx: iniciadas en el enrutador del componente raíz
  • rutas relativas xxx: iniciadas en el enrutador del componente actual
  • rutas relativas ../xxx: iniciadas en el enrutador principal del componente actual
Günter Zöchbauer
fuente
Aunque este código puede responder a la pregunta, proporcionar un contexto adicional sobre por qué y / o cómo responde la pregunta mejoraría significativamente su valor a largo plazo. Por favor, editar su respuesta a añadir un poco de explicación.
Toby Speight
1
@TobySpeight Bastante justo. Supuse que ../se conoce bastante bien, pero al final sigue siendo ambiguo. Gracias por la pista.
Günter Zöchbauer
1
Gracias por la respuesta, he estado trabajando en este sitio web durante bastante tiempo, por lo que Angular obviamente se ha actualizado desde entonces. Probé esta solución en mi versión actual y no funciona. Déjame actualizar y volveré a comentar después.
Carl Boisvert
1
No consigo que su código funcione como se esperaba. Sin embargo, al agregar explícitamente , {relatedTo: this.route} como segundo parámetro en la llamada para navegar , funciona. Lo atribuiría a un error tipográfico estúpido si no hubiera sido por el hecho de que sus respuestas generalmente tienen un grado extremo de precisión. ¿Es quizás un cambio en el comportamiento del enrutador desde que se proporcionó la respuesta (hace 3.6 años, que en los años angulares es como una eternidad a medias)?
Konrad Viltersten
Esta es una respuesta antigua y el enrutador cambió mucho en este momento. Creo que mi respuesta está desactualizada considerando que hay varias respuestas con más votos a favor. Ya no estoy haciendo tantas cosas de la interfaz de usuario web y no tengo todos los detalles en la parte superior de mi cabeza.
Günter Zöchbauer
6

Para navegar al componente principal independientemente del número de parámetros en la ruta actual o la ruta principal: Actualización de Angular 6 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);

Esto tiene la ventaja adicional de ser una ruta absoluta que puede usar con el enrutador singleton.

(Angular 4+ seguro, probablemente Angular 2 también).

Kayjtea
fuente
extrañamente, esto siempre devuelve una matriz vacía y logra el mismo resultado que this._router.navigate([]), while this._router.navigate([[]])lleva a la ruta principal, si y solo si la ruta principal no es la raíz misma.
Ashish Jhanwar
código actualizado para reflejar los cambios de Angular 6 y la búsqueda de padres adecuada con padres e hijos que contienen hijos en las rutas.
Don Thomas Boyle
¿Está seguro de que esto no es algo específico para su caso de uso? Parecería que no agregar la última ruta convertiría ['pedidos', '123', 'elementos', 1] en solo ['pedidos'], lo que no parece correcto en absoluto. En cualquier caso, pasamos de Angular 5 a 7 y no tocamos este código.
kayjtea
Hay un número de div en mi página ... al hacer clic en cada div, paso los parámetros de consulta y cargo un componente. ahora usando el botón de retroceso del navegador quiero volver, ¿cómo se hace?
Vrajendra Singh Mandloi
4

Otra forma podría ser así

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

y aqui esta el constructor

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

sin mucho preámbulo:

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

el parámetro '..' hace que la navegación suba un nivel, es decir, padre :)

Igor Zinin
fuente
Es posible que desee mencionar el propósito / necesidad de skipLocationChange .
Konrad Viltersten
1

Mis rutas tienen un patrón como este:

  • usuario / editar / 1 -> Editar
  • usuario / crear / 0 -> Crear
  • usuario / -> Lista

Cuando estoy en la página Editar, por ejemplo, y necesito volver a la página de la lista, regresaré 2 niveles arriba en la ruta.

Pensando en eso, creé mi método con un parámetro de "nivel".

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

Entonces, para pasar de la edición a la lista, llamo al método así:

this.goBack(2);
Carlinhos
fuente
0

agregue Ubicación a su constructor desde @angular/common

constructor(private _location: Location) {}

agregar la función de retroceso:

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

y luego en tu opinión:

<button class="btn" (click)="back()">Back</button>
user3021615
fuente
5
Esto solo funciona si estaba en la ruta principal anteriormente. Las rutas principales no tienen nada que ver con el historial del navegador ...
leviathanbadger
navega hacia atrás, pero no navega al padre del componente
Andrew Andreev
Esto no debe usarse, si el usuario accede al componente desde un sitio externo, sería llevado de regreso a ese sitio. Este código es lo mismo que hacer clic en el BOTÓN ATRÁS DEL NAVEGADOR
T04435
0

Si está utilizando la directiva uiSref, puede hacer esto

uiSref="^"
Zuriel
fuente
0

Mi solucion es:

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

Y la Routerinyección:

private readonly _router: Router
anlijudavid
fuente