Handling loading and error states with Angular’s async pipe

How to deal with loading and error states when using the Angular async pipe

Posted on December 17, 2020

Tags:

Angular

Here’s a simple of way of handling loading and error states when using Angular’s async pipe.

For larger applications I’d create a resuable ‘loading’ component to avoid code duplication. This also makes it easier to update if you need to tweak the markup.

Component

import {Component, OnInit} from '@angular/core';
import {ArticleService} from '../../services/article/article.service';
import {Observable} from 'rxjs';
import {catchError} from 'rxjs/operators';

@Component({
    selector: 'app-home',
    templateUrl: './home.component.html',
    styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {

    articles: Observable;
    articleErrorObject: {};

    constructor(private _articleService: ArticleService) {
    }

    ngOnInit() {
        this.articles = this._articleService.getArticles().pipe(
            catchError(err => {
                this.articleErrorObject = err;
            })
        );
    }
}

Template

<section>

    <ng-container *ngIf="articles | async as article; else loadingOrError">
        <article *ngFor="let a of article">
            <h2>{{a.title}}</h2>
        </article>
    </ng-container>

    <ng-template #loadingOrError>
        <article *ngIf="articleErrorObject; else isLoading">
            <p>Houston, we have a problem</p>
        </article>
        <ng-template #isLoading>
            <article>
                <p>Loading…</p>
            </article>
        </ng-template>
    </ng-template>

</section>