Set URL for canceled path when redirecting to 404 page using resolver

Let's say we have the following route configuration:

[{ path: "people", children: [ { path: ":id", component: PersonProfileComponent, resolve: { person: PersonResolver }, children: [ { path: "", component: PersonOverviewComponent }, { path: "photos", component: PersonPhotoListComponent } ] } ] }, { path: "404", component: PageNotFoundComponent }, { path: "**", component: PageNotFoundComponent }] 

I want to redirect to page 404 when the user tries to go to any of them:

 /people/{non-existing-id} /people/{non-existing-id}/photos /people/{existing-id}/{non-existing-subpage} 

The third case is handled by the ** route, since it does not match any of the previous routes. Thus, PersonResolver must handle the first two cases.

 export class PersonResolver implements Resolve<Person> { constructor(private peopleService: PeopleService, private router: Router) { } resolve(route: ActivatedRouteSnapshot): Observable<Person> { return this.peopleService.find(id).catch(error => { if (error instanceof Response) { if (error.status === 404) { this.router.navigate(["/404"]); } else { //todo } } else { //todo } return Observable.of(null); }); } } 

Everything works, but the problem is that when the 404 page is displayed, the browser URL is updated to <hostname>/404 (as expected). My question is how to set the URL of the path just canceled (e.g. <hostname>/people/fake-id/photos ), since this 404 is handled all over the Internet. (I also tried passing {skipLocationChange: true} to router.navigate() , but this saves space before we try to jump)

+5
source share
2 answers

Change URLs without navigation with Location - docs possible

You can respond to the error with subscribing to Router.events - NavigationError , then show 404 with skipLocationChange and then change the location with location.go

You need to change the URL after completing the 404 navigation.

  constructor(router: Router, location: Location) { router.events .filter(event => event instanceof NavigationError) .subscribe((event: NavigationError) => { router.navigate(["/404"], {skipLocationChange: true}) .then(() => location.go(event.url)); }) } 

I would prefer to do this in my routing module, but this could also be done in resolver.

Router.events is not very well documented yet, you can check at least a list of them here and make some entries.

+3
source

@ Víťa Plšek was really good for inspiration, but it did not work for me.

Here is how I did it:

  resolve( route: ActivatedRouteSnapshot, state: RouterStateSnapshot, ): Observable<any> | Promise<any> | any { // Do some stuff that fails... // Redirect to 404. return this.router.events .filter(event => event instanceof NavigationEnd) .first() .subscribe((event: NavigationError) => ( this.router.navigate(['/404'], {skipLocationChange: true}) .then(() => this.location.go(event.url)) )); } 

Pure version:

my component-resolver.ts

 @Injectable() export class YoutubeVideoResolver { constructor( private resolverNavigation: ResolverNavigation, private router: Router, private http: Http, ) {} resolve( route: ActivatedRouteSnapshot, state: RouterStateSnapshot, ): Observable<any> | Promise<any> | any { this.http.get('/foo') .map((response) => { // Found. Do something with the data. }) .catch((error) => { // Not found. Redirect to 404. this.resolverNavigation.to404(); return Observable.of(null); }); } } 

resolver-navigation.ts

 import { Injectable } from '@angular/core'; import { Location } from '@angular/common'; import { ActivatedRoute } from '@angular/router'; import { Router, NavigationEnd, } from '@angular/router'; import { Observable } from 'rxjs/Observable'; @Injectable() export class ResolverNavigation { constructor( private router: Router, private location: Location, ) {} to404(): void { this.router.events .filter(event => event instanceof NavigationEnd) .first() .subscribe((event: NavigationEnd) => ( this.router.navigate(['/404'], {skipLocationChange: true}) .then(() => this.location.go(event.url)) )); } } 
0
source

Source: https://habr.com/ru/post/1263012/


All Articles