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.