如何从子路线导航到父路线?


89

我的问题很经典。我在后面有一个应用程序的私有部分login form。登录成功后,它将转到管理应用程序的子路由。

我的问题是我无法使用,global navigation menu因为路由器会尝试以我的路由AdminComponent而不是我的路由AppCompoment。所以我的导航坏了。

另一个问题是,如果有人想直接访问URL,我想重定向到父级“登录”路由。但是我不能使它工作。在我看来,这两个问题是相似的。

知道如何做到吗?


3
请添加一些代码
江YD

Answers:


153

您要链接/ HTML,还是要强制性地/以代码形式路由?

链接:RouterLink指令始终将提供的链接视为当前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"

使用RouterLink时,请记住导入并使用该directives数组:

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

势在必行:该navigate()方法需要一个起始点(即,relativeTo参数)。如果未提供任何内容,则导航是绝对的:

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
router.navigate(string)当前版本的Angular(2.2)中似乎不存在该方法。我在文档中搜索后才发现navigate(commands: any[], extras?: NavigationExtras) : Promise<boolean>。还是我完全错过了什么?
番茄

2
@西红柿,您需要在路线周围加上[]。例如,this.router.navigate([“ ../../ parent”],{relativeTo:this.route});
gye

2
relativeTo当您在HTML中使用[routerLink]而不是打字稿时,如何传递数据?
redfox05

与服务相同吗?
oCcSking

出于某种原因,在我的情况下,我必须使用../../../而不是../导航到父对象('/users''/users/1')。
nelson6e65

47

截至2017年春季,这似乎对我有用:

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

您的组件ctor接受ActivatedRouteRouter导入的位置,如下所示:

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


4
提起您碰巧正在使用的Angular版本,它比日期更有用。
isherwood

@艾舍伍德我同意。道歉。如果我没记错的话,我是为Angular 4.0.x编写的,它在4.3.x中仍然可以使用。不幸的是,我现在已离开Angular
ne1410s

@ ne1410s非常感谢亲戚:this.route
伊恩·萨姆斯

注意:不适用于延迟加载的模块上的其他路由器网段。EX::parentPath'work:queue'(有孩子),说孩子加载带有参数的孩子模块。fullCurrentPath:“工作/运输/模块/列表”。上面的代码无法parentPath从加载fullCurrentPath
唐·汤玛斯·博伊尔

32

您可以像这样导航到您的父根

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

您将需要在构造函数中注入当前活动的Route

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

  }

2
添加一些解释会使此答案更有用。
Sagar Zala

许多人建议使用this.router.navigate([“ ../ sibling”],{relativeTo:this.route})导航到同级。但是,这不再起作用。我发现此答案可能有效。而不是使用“ ../”导航到父级。从this.route更改relativeTo到this.route.parent是正确的方法
Terry Lam

1
@ChrisLamothe:哦,是的,我犯了一个错误。一般情况下都可以使用。但是,它不适用于辅助路线。这意味着this.router.navigate(['../ sibling'])正常工作,但没有this.router.navigate([{outlets:{'secondary':['../sibling']}}])。在辅助路由中,我必须使用this.router.navigate([[outlet:{'secondary':['sibling']}}],{relativeTo:this.activatedRoute.parent})。
Terry Lam

2
另外,this.router.navigate(['.'], {relativeTo: this.activeRoute.parent});如果您在以下两个路径中使用相同的组件:/ users / create和/ users / edit / 123 ,则此答案中的导航方法将正常工作。在这两种情况下,它都将导航到父/用户。常规导航this.router.navigate([".."], {relativeTo: this.activeRoute})仅适用于用户/创建,但不适用于用户/ edit / 123,因为它将导航至不存在的/用户/编辑/路线。
Roganik

1
+1是一种替代选择,但就我个人而言,我有点追逐字节,并且会在参数[“ ..”]中添加一个额外的点,以消除对父项{relativeTo:this.route}的引用。
康拉德·维特尔斯滕

7
constructor(private router: Router) {}

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

路由器支持

  • 绝对路径/xxx-在根组件的路由器上启动
  • 相对路径xxx-在当前组件的路由器上启动
  • 相对路径../xxx-从当前组件的父路由器开始

尽管此代码可以回答问题,但提供有关其为什么和/或如何回答问题的其他上下文将显着提高其长期价值。请编辑您的答案以添加一些说明。
Toby Speight,

1
@TobySpeight足够公平。我以为大家../都知道,但最后还是模棱两可。感谢您的提示。
君特Zöchbauer

1
感谢您的回答,我已经在这个网站上工作了一段时间,因此Angular显然已经进行了更新。我已经在当前版本中尝试过此解决方案,但该解决方案无法正常工作。让我更新,稍后再评论。
卡尔·博伊斯维特

1
我没有让您的代码按预期工作。但是,通过显式添加,{relativeTo:this.route}作为对Navigation的调用中的第二个参数,它可以工作。如果不是因为您的答案通常具有极高的准确性,我会把它归类为愚蠢的错字。自从提供答案以来(3.6年前,在Angular时代就像半个世纪的永恒),这可能是路由器行为的变化吗?
Konrad Viltersten

这是一个古老的答案,路由器此时发生了很大变化。考虑到有几个答案需要更多支持,我认为我的答案已经过时了。我不再做太多的Web UI工作,并且没有所有细节都放在我的头上。
君特Zöchbauer

6

无论当前路径或父路径中有多少参数,都要导航到父组件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);

这是您可以与单例路由器一起使用的绝对路由的额外好处。

(当然,Angular 4+也可能是Angular2。)


古怪,这总是返回一个空数组,并达到相同的结果 this._router.navigate([]),而this._router.navigate([[]])需要与母体路线,当且仅当父路由不是根本身。
Ashish Jhanwar

更新了代码,以反映Angular 6的更改以及路线中包含父级和子级的孩子的正确父级查找。
唐·汤玛斯·博伊尔

您确定这不是您的用例所特有的吗?似乎不附加最后一条路径会使['orders','123','items',1]变成['orders'],这似乎根本不正确。无论如何,我们只是从Angular 5转到了7,并没有碰到这个编码。
kayjtea

它们是我页面上的div数..单击每个div时,我将传递查询参数并加载组件。现在使用浏览器的后退按钮,我想返回该怎么做?
Vrajendra Singh Mandloi

4

另一种方式可能是这样的

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

这是构造函数

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


1

我的路线具有以下模式:

  • 用户/编辑/ 1->编辑
  • 用户/创建/ 0->创建
  • 用户/->列表

例如,当我在“编辑”页面上并且需要返回列表页面时,我将在路线上返回2个级别。

考虑到这一点,我创建了一个带有“级别”参数的方法。

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

因此,要从编辑转到列表,我将调用如下方法:

this.goBack(2);

0

将位置从添加到构造函数 @angular/common

constructor(private _location: Location) {}

添加后退功能:

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

然后您认为:

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

5
仅当您以前在父路径中时,此方法才有效。父路径与浏览器历史记录无关...
leviathanbadger

它会向后导航,但不会导航到组件的父级
Andrew Andreev

不应使用此方法,如果用户从外部站点转到该组件,则会将其带回该站点。此代码与单击浏览器中的“ BACK”按钮相同
T04435 '18

0

如果您使用的是uiSref指令,则可以执行此操作

uiSref="^"

0

我的解决方案是:

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

Router注射:

private readonly _router: Router
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.