How do I navigate to a parent route from a child route?
AngularAngular RoutingAngular RouterAngular Problem Overview
My problem is quite classic. I have a private part of an application which is behind a login form
. When the login is successful, it goes to a child route for the admin application.
My problem is that I can't use the global navigation menu
because the router tries to route in my AdminComponent
instead of my AppCompoment
. So my navigation is broken.
Another problem is that if someone want to access the URL directly, I want to redirect to the parent "login" route. But I can't make it work. It seems to me like theses two issues are similar.
Any idea how it can be done?
Angular Solutions
Solution 1 - Angular
Do you want a link/HTML or do you want to route imperatively/in code?
Link: The RouterLink directive always treats the provided link as a delta to the current 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"
With RouterLink, remember to import and use the directives
array:
import { ROUTER_DIRECTIVES } from '@angular/router';
@Component({
directives: [ROUTER_DIRECTIVES],
Imperative: The navigate()
method requires a starting point (i.e., the relativeTo
parameter). If none is provided, the navigation is absolute:
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});
Solution 2 - Angular
This seems to work for me as of Spring 2017:
goBack(): void {
this.router.navigate(['../'], { relativeTo: this.route });
}
Where your component ctor accepts ActivatedRoute
and Router
, imported as follows:
import { ActivatedRoute, Router } from '@angular/router';
Solution 3 - Angular
You can navigate to your parent root like this
this.router.navigate(['.'], { relativeTo: this.activeRoute.parent });
You will need to inject the current active Route in the constructor
constructor(
private router: Router,
private activeRoute: ActivatedRoute) {
}
Solution 4 - Angular
constructor(private router: Router) {}
navigateOnParent() {
this.router.navigate(['../some-path-on-parent']);
}
The router supports
- absolute paths
/xxx
- started on the router of the root component - relative paths
xxx
- started on the router of the current component - relative paths
../xxx
- started on the parent router of the current component
Solution 5 - Angular
without much ado:
this.router.navigate(['..'], {relativeTo: this.activeRoute, skipLocationChange: true});
parameter '..' makes navigation one level up, i.e. parent :)
Solution 6 - Angular
Another way could be like this
this._router.navigateByUrl(this._router.url.substr(0, this._router.url.lastIndexOf('/'))); // go to parent URL
and here is the constructor
constructor(
private _activatedRoute: ActivatedRoute,
private _router: Router
) { }
Solution 7 - Angular
To navigate to the parent component regardless of the number of parameters in the current route or the parent route: 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);
This has the added bonus of being an absolute route you can use with the singleton Router.
(Angular 4+ for sure, probably Angular 2 too.)
Solution 8 - Angular
My routes have a pattern like this:
- user/edit/1 -> Edit
- user/create/0 -> Create
- user/ -> List
When i am on Edit page, for example, and i need go back to list page, i will return 2 levels up on the route.
Thinking about that, i created my method with a "level" parameter.
goBack(level: number = 1) {
let commands = '../';
this.router.navigate([commands.repeat(level)], { relativeTo: this.route });
}
So, to go from edit to list i call the method like that:
this.goBack(2);
Solution 9 - Angular
None of this worked for me ... Here is my code with the back function :
import { Router } from '@angular/router';
...
constructor(private router: Router) {}
...
back() {
this.router.navigate([this.router.url.substring(0, this.router.url.lastIndexOf('/'))]);
}
this.router.url.substring(0, this.router.url.lastIndexOf('/') --> get the last part of the current url after the "/" --> get the current route.
Solution 10 - Angular
If you are using the uiSref directive then you can do this
uiSref="^"
Solution 11 - Angular
My solution is:
const urlSplit = this._router.url.split('/');
this._router.navigate([urlSplit.splice(0, urlSplit.length - 1).join('/')], { relativeTo: this._route.parent });
And the Router
injection:
private readonly _router: Router
Solution 12 - Angular
This might help: https://angular.io/api/router/ExtraOptions#relativeLinkResolution
> ExtraOptions interface
> A set of configuration options for a router module, provided in the forRoot() method.
> > interface ExtraOptions { > // Others omitted > relativeLinkResolution?: 'legacy' | 'corrected' > } >
>
>
> relativeLinkResolution?: 'legacy' | 'corrected'
>
> Enables a bug fix that corrects relative link resolution in components with empty paths.
>
<<snip>>
> The default in v11 is corrected.
I've been struggling with routing the last couple of days, turns out there used to be a bug in relative routing. This fixes it.
Solution 13 - Angular
add Location to your constructor from @angular/common
constructor(private _location: Location) {}
add the back function:
back() {
this._location.back();
}
and then in your view:
<button class="btn" (click)="back()">Back</button>