DEV Community

Anirban Mukherjee
Anirban Mukherjee

Posted on

Global error page in Angular

This is a relatively small and simple article, but I felt it is still worth posting because of the utility of the topic.

GitHub logo anirbmuk / angular-error-handler

Angular 12 application to demonstrate global error handling against a REST-based backend

Any front-end application is all about serving data from a store, using end-points (REST/GraphQL or whichever you can think of). And a big part of your application's success is the way you can handle errors. The more gracefully you handle error situations, the better your users' experience will be.

Preview

On that note, let's talk about an approach to handle all sorts of errors in an Angular application.

The idea behind this article is to manage all possible errors in one location and allow the application to navigate to an error-page once any error is thrown. Now I would like to clarify that when I say error, I mean server side errors, emanating from your data end-points.

To do this, we will make use of the one place through which every HTTP request passes in an angular application - the interceptor. We usually make use of the interceptor to tap outgoing requests and append headers, tokens etc. But we can also tap onto the incoming response and handle the error situations.

When the next: HttpHandler handles the request, the request is sent to the back-end server. We can pipe the observable to tap onto the incoming response.

interceptor.service.ts:
intercept(
    req: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    return next.handle(req).pipe(
      catchError((error) => {
        const { code, message } = error.error;
        this.errorService.addError({
          code: code || error?.status,
          message: message || error?.statusText,
        });
        this.router.navigate(['/error']);
        return EMPTY;
      })
    );
  }
Enter fullscreen mode Exit fullscreen mode

We also navigate to our designated error page, which is designed to handle the error code and message and display it appropriately.

Additional improvisation: Use a resolver for the error component and check if the error observable has any value. If not then redirect to the home-page. This may be helpful when the user refreshes the error page; then it would make more sense to be taken to the home page to try again, instead of showing the same error once again.

error.resolver.ts:
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    return this.errorService.error$.pipe(
      take(1),
      tap((data) => {
        if (!data) {
          throw new Error('No error');
        }
      }),
      catchError(() => {
        this.router.navigate(['/']);
        return of(null);
      })
    );
  }
Enter fullscreen mode Exit fullscreen mode

Cheers!
Follow me on Twitter or connect with me on LinkedIn

Discussion (4)

Collapse
kostyatretyak profile image
Костя Третяк

As far as I understand, all errors are redirected to the /error path. Right? The best option is to show the error page on the path where the user went. At the moment (Angular 13) there is no such built-in feature, so we have to come up with workarounds.

See solution on stackblitz

Collapse
anirbmuk profile image
Anirban Mukherjee Author

It is an interesting point. The only problem I see with this approach is the need to write an error handler inside every route resolver. That kind of makes the components lose their purpose. I believe all the user needs is to navigate back to the page where he/she came from, and for that we can make use of @angular/common's Location class.

Another approach is - (if we want to stay on the same page) - is to use { skipLocationChange: true } when we navigate to /error.

Collapse
kostyatretyak profile image
Костя Третяк

That kind of makes the components lose their purpose.

No, it's not. On the contrary, we can use the components to the fullest, because we can use the appropriate component for the error handler:

<ng-container *ngIf="!httpErrorResponse">
  Current component code here
</ng-container>

<cst-http-errors [httpErrorResponse]="httpErrorResponse"></cst-http-errors>
Enter fullscreen mode Exit fullscreen mode
Collapse
oliverdjbrown profile image
Oliver Brown

Excellent articule thanks