5

I have a simple resolver for a route like /orders/first:

resolve(): Promise<Order> {
    return this.orderService.get()
        .then((response) => response.order)
        .catch(error => Promise.reject(error));
}

I also have an error handler that redirects to an error page:

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

I want the URL to be /orders/first so if the user refresh he might be able to view the page. This also make back button return to an incorrect page (previous previous page)

The problem is that the resolver runs before route activation so the URL doesn't change.

Is there a way to do this?


EDIT: Found this workaround:

  1. Listen to router event NavigationStart and save route to a variable
  2. Set location URL before redirecting to error page: this.location.go(nextRoute.url);
  3. Redirect with skipLocationChange set to true
1
  • Hi Tzach. Can you provide a sample/gist with your implementation? I need to have the same behaviour in an app that you described. Commented Jan 31, 2018 at 12:49

2 Answers 2

2

I have achieved this this way:

resolve(
  route: ActivatedRouteSnapshot,
  state: RouterStateSnapshot
): Observable<any>|Promise<any>|any {
  return this.clientService.get(route.params.id)
  .catch( err => {
    const path = this.location.path();
    this.router.navigate(["/" + err.status], {  skipLocationChange: true })
    .then( () => {
      this.location.replaceState(path);
    });

    return Observable.empty();
  })
}
Sign up to request clarification or add additional context in comments.

Comments

2
import { Injectable } from '@angular/core';
import { Router, NavigationError, NavigationExtras } from '@angular/router';
import { Location } from '@angular/common';

@Injectable()
export class RouterService {

    private errorRoot: string;

    constructor(
        private router: Router,
        private location: Location
    ) { }

    setRouteErrorHandler(errorRoot: string = '/error'): void {
        let errorRoute = null;
        this.errorRoot = errorRoot;
        this.router.errorHandler = (error): void => {
            this.router.navigateByUrl(errorRoot, { skipLocationChange: true })
                .then(() => this.location.go(errorRoute.url));
        };

        this.router.events
            .filter(next => next instanceof NavigationError)
            .subscribe((next) => errorRoute = next);
    }
}

And call routerService.setRouteErrorHandler() from AppModule constructor or APP_INITIALIZER

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.