How to Handle Errors in a Reactive Angular App

Share on facebook
Share on google
Share on twitter
Share on linkedin

In this post, we will cover how to handle errors in a reactive Angular app. To provide a good user experience you should always let your users know what state your application is in. That includes showing a loading spinner when it’s loading and showing error messages if there are any errors.

It is a common pattern that a page consists of the main content alongside a loading screen and some error messages in case of errors.
We will cover a helpful pattern you can follow for creating Angular components that follow this way of working.

The Pattern

Generally, the pattern works like this code:

<ng-container *ngIf="(isLoading$ | async) === false; else loading">
    <ng-container *ngIf="!(error$ | async); error">
        <!-- Content -->
    </ng-container>

    <ng-template #error>
        <ng-container [ngSwitch]="error$ | async">
            <ng-container *ngSwitchCase="someError1">
                <!-- Error message -->
            </ng-container>
            <ng-container *ngSwitchCase="someError2">
                <!-- Error message -->
            </ng-container>
    </ng-template>
</ng-container>

<ng-template #loading>
    <!-- Loading indicator -->
</ng-template>

We first check if we are loading and show a loading spinner in case. Then we show the content if there are no errors or use a ngSwitch to show the error corresponding to that error.

The error$ can be an error id derived from a selector or set in your state when an error has happened eg. “Couldn’t load data. Try again”.

Sometimes, you want to show the content and errors simultaneously and that would look like this:

<ng-container *ngIf="(isLoading$ | async) === false; else loading">
    <ng-container *ngIf="!(error$ | async)">
        <!-- Content -->
    </ng-container>

    <ng-container *ngIf="(error$ | async) as error">
        <ng-container [ngSwitch]="error">
            <ng-container *ngSwitchCase="someError1">
                <!-- Error message -->
            </ng-container>
            <ng-container *ngSwitchCase="someError2">
                <!-- Error message -->
            </ng-container>
    </ng-container>
</ng-container>

<ng-template #loading>
    <!-- Loading indicator -->
</ng-template>

Here we simply allow the content and error to be shown simultaneously if there are any errors.

With Signals

It’s even simpler with Signals and the $ + async just becomes calling the signals getter/().

<ng-container *ngIf="isLoading() === false; else loading">
    <ng-container *ngIf="!error(); error">
        <!-- Content -->
    </ng-container>

    <ng-template #error>
        <ng-container [ngSwitch]="error()">
            <ng-container *ngSwitchCase="someError1">
                <!-- Error message -->
            </ng-container>
            <ng-container *ngSwitchCase="someError2">
                <!-- Error message -->
            </ng-container>
    </ng-template>
</ng-container>

<ng-template #loading>
    <!-- Loading indicator -->
</ng-template>

Conclusion

We learned a pattern to architect your pages so you show spinner, content, and error messages in a reactive way.

Do you want to become an Angular architect? Check out Angular Architect Accelerator.

Related Posts and Comments

New Angular project? This is how I would start

Throughout my career as an Angular consultant, I have had occasions where I had to start with an Angular project from scratch which is a pipe dream for every software developer. Do everything the right way at the get-go, no legacy, you follow me… So, how do you get started with the project from scratch,

Read More »

Error, loading, content…? Use this page pattern for your Angular apps

When developing Angular applications, it’s common for pages to transition through three key states: error, loading, and show content. Every time you fetch data from an API, your page will likely show a loading indicator first, and then either render the content successfully or display an error message if something goes wrong. This pattern is

Read More »

How to do Cypress component testing for Angular apps with MSW

In this post, we will cover how to do Cypress Component testing with MSW (mock service worker) and why it’s beneficial to have a mock environment with MSW. The mock environment My recommendation for most enterprise projects is to have a mocking environment as it serves the following purposes : * The front end can

Read More »

Handling Authentication with Supabase, Analog and tRPC

In this video, I cover how to handle authentication with Supabase, Analog and tRPC. It’s based on my Angular Global Summit talk about the SPARTAN stack you can find on my blog as well. Code snippets Create the auth client Do you want to become an Angular architect? Check out Angular Architect Accelerator.

Read More »

Leave a Comment

Your email address will not be published. Required fields are marked *