Presentation of information with loading and error scenarios

How can we effectively display data in an Angular view, considering loading state and error handling?

Imagine we are fetching a set of documents from our backend and need to present them in an Angular view. We want to address three possible scenarios by providing corresponding messages to the user:

  1. Loading your data...
  2. Error trying to retrieve your data!
  3. Data retrieved successfully!

Currently, my approach involves displaying both the "loading" and "error" messages briefly during the data retrieval process.

I am curious about how others tackle this common scenario. Is it feasible to manage this by manipulating the myDocs variable, or should I introduce another variable for better control?

Typescript Implementation (TS)

export class MyDocsComponent implements OnInit {

    myDocs: IMyDoc | null;

    ngOnInit() {

        // fetch myDocs
        this.myDocsService.getMyDocs()

        // if successful
        .then( myDocs => { this.myDocs = myDocs; })

        // if there's an error while retrieving myDocs from the service
        .catch( error => {
            // What actions should be taken here?
            // How can this be managed in the view 
            // to inform the user that data retrieval failed?
            // And also display a loading message prior to this.

            // Currently, I am using:
            this.myDocs = null;
            // However, this results in the error message 
            // being displayed prematurely during data loading.
        });
    }
}

HTML Markup (HTML)

<!-- Loading State -->
<div class="loading" *ngIf="!myDocs">
    Loading your data...
</div>

<!-- Error State -->
<div class="error" *ngIf="myDocs==null">
    Error trying to retrieve your data!                         
</div>

<!-- Success State -->
<div class="success" *ngIf="myDocs">
    Data retrieved successfully!
    <div class="list" *ngFor="let d of myDocs">{{ d.title }}</div>
</div>

Answer №1

Here is an example you can try out

file.component.ts

export class MyDocsComponent implements OnInit {

  myDocs: IMyDoc | null;

  state: 'loading' | 'loaded' | 'error' = 'loading';

  isLoading() {
    return this.state === 'loading';
  }

  isError() {
    return this.state === 'error';
  }

  isLoaded() {
    return this.state === 'loaded';
  }

  ngOnInit() {
    this.myDocsService.getMyDocs()
      .then(myDocs => {
        this.myDocs = myDocs;
        this.state = 'loaded';
      })
      .catch(error => {
        console.log(error);
        this.state = 'error';
      });
  }
}

file.component.html

<div *ngIf="isLoading"  class="loading">
  Loading your data...
</div>

<div *ngIf="isError" class="error">
  Error trying to retrieve your data!
</div>

<div *ngIf="isSuccess" class="success" >
  Data retrieved successfully!
  <div class="list" *ngFor="let d of myDocs"> {{ d.title }}
  </div>
</div>

Answer №2

Here is an alternative solution to address the issue at hand. In response to the OP's request, I have relocated it to a different answer. Please refrain from upvoting this.

This method involves leveraging some more advanced features in Angular such as

  • async pipe,
  • <ng-container>,
  • as keyword within the *ngIf statement,
  • else loading paired with <ng-template #loading>.

component.ts

export class MyDocsComponent implements OnInit {
  myDocs$: Promise<IMyDoc | string>;

  ngOnInit() {
    this.myDocs$ = this.myDocsService.getMyDocs()
      .then(response => {
        console.log('Data retrieved successfully');
        return response;
      })
      .catch(error => {
        console.log(error);
        return 'An error occurred';
      });
  }

  isError(resp: IMyDoc | string) {
    return typeof resp === 'string';
  }

  isSuccess(resp: IMyDoc | string) {
    return typeof resp !== 'string';
  }
}

component.html

<div *ngIf="myDocs$ | async as myDocs; else loading">
  <ng-container *ngIf="isSuccess(myDocs)">
    <div class="success"
      Data retrieved successfully!
      <div class="list" *ngFor="let d of myDocs"> {{ d.title }}
      </div>
    </div>
  </ng-container>

  <ng-container *ngIf="isError(myDocs)">
    <div class="error">
      Error retrieving data!
    </div>
  </ng-container>
</div>

<ng-template #loading>
  <div *ngIf="isLoading" class="loading">
    Loading data...
  </div>
</ng-template>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Encountered a problem while trying to set up the Angular Material Library that has been cloned from

Trying to setup a library that has been forked from https://github.com/angular/material2. git clone <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="63040a1723040a170b16014d000c0e">[email protected]</a>:vugar005/m ...

Encountering SUID Sandbox Helper Issue When Running "npm start" on WSL with Electron and Typescript

Can anyone help me with this issue? I have Node v8.10.0 and I'm attempting to follow a beginner tutorial on Electron + Typescript which can be found at the following link: https://github.com/electron/electron-quick-start-typescript Here is the full e ...

Tips for successfully passing a prop to a custom root component in material-ui@next with TypeScript

Is there a way to properly render a ListItem component with react-router Link as the root component? Here's the code snippet in question: <ListItem to="/profile" component={Link} > Profile ...

Uncovering redundant fields in TypeScript and detecting errors through type inference

Encountering an unusual edge case with the TS compiler regarding type inference. Surprisingly, the code snippet below (with commented lines intact) should trigger a compile error, but it doesn't. interface IReturned { theField?: string; } interfa ...

Can type information be incorporated during compilation?

Consider the code snippet below: function addProperties(keys: String[]): Object { // For illustration purposes, this is a specific return return { firstProperty: "first_value", secondProperty: "second_value" }; } export defaul ...

Tips for displaying an associative object array as td elements within a tbody in Nuxt

I'm having trouble displaying the property of an associative object array in my code. I attempted to utilize a v-for loop and wanted to showcase the property information within the td elements of a tbody. I am aware that v-data-table components have a ...

The Highcharts xrange series is encountering the error message "x is not a function."

I am currently working in an Angular 4 (Angular-cli) environment and attempting to utilize the x-range highcharts type. After executing the npm install command npm install highcharts --save, I included these lines of code: import * as Highcharts from &ap ...

Setting the initial selected option in a dropdown using Angular 4 Reactive Forms

One of the challenges I faced in Angular 4 was displaying a dropdown list with countries using a Reactive module. To achieve this, I had set up a configuration in a json file as follows: countries: ['USA', 'UK', 'Canada']; ...

Can someone guide me on finding my staticwebapp.config.json within Azure Devops for deploying Azure Static Web Apps during a release?

After setting up a pipeline to build the artifact for my Angular application, I encountered an issue with deployment where specific URLs would redirect me to a 404 error page. This problem seems to be related to the configuration in staticwebapp.config.jso ...

Tips for showcasing nested objects in Angular components

I'm faced with a situation where there is an object containing several nested objects, each with their own set of values. How can I display the key values from this complex data structure? I suspect using *ngFor might not provide the solution. const d ...

Accessing user information after logging in can be achieved through utilizing Web API in conjunction with Angular 5 Token Authentication

Every time I access my Angular app, the following information is displayed: access_token:"******************" expires_in:59 refresh_token:"******************" token_type:"bearer" However, I am now facing an issue where I cannot extract the user id from t ...

Tips for accessing the app instance within a module in Nest.js

Currently, I am involved in a project that relies on multiple Nest repositories, approximately 4 in total. Each repository must integrate logging functionalities to monitor various events such as: Server lifecycle events Uncaught errors HTTP requests/resp ...

Utilizing the power of the Google Calendar API with a service account in a Node.js environment

I have a vision to create an application with a specific feature set: Whenever there is a change in the user's Google calendar (an event is added, deleted, or edited), I want to receive updates with full event details. To achieve this, I understand ...

Unusual conduct exhibited by a 16th version Angular module?

I've created a unique component using Angular 16. It's responsible for displaying a red div with a message inside. import { ChangeDetectionStrategy, Component, Input, OnInit, } from "@angular/core"; import { MaintenanceMessage } ...

Creating a custom directive in Angular 2 that restricts input to text only

I have recently created a directive that specifically allows only numbers by using key codes. However, I've noticed that when I try to copy and paste text into the text box, it accepts the input but does not display it. Is there a way to utilize &apo ...

M.E.A.N - Suite for setting up and defining backend boundaries consisting of MongoDB, Express.js, Angular2, node.js

Seeking knowledge on how the frameworks and platforms Angular 2 and Express.js collaborate in the 'mean' approach is my main query. I am interested in understanding where the client-side ends and the server-side begins. After delving into this t ...

Can we verify if this API response is accurate?

I am currently delving into the world of API's and developing a basic response for users when they hit an endpoint on my express app. One question that has been lingering in my mind is what constitutes a proper API response – must it always be an o ...

Steps to deactivate a button in an Angular reactive form upon submission

I am working with Angular reactive forms and I need to implement a functionality where the button is disabled and its label changes after it has been clicked or submitted. Any suggestions on how to achieve this? ...

NativeScript does not acknowledge the permission "android.Manifest.permission.READ_CONTACTS"

Hi there! I am a beginner in mobile development and currently learning Angular 2. I am facing an issue with requesting permission for reading contacts in NativeScript. It seems that "android" is not being recognized. For instance, when trying to execute t ...

There are no imports in index.js and there is no systemjs configuration set up

After creating a fresh Angular project using ng new some-name, I noticed that the generated index.html file does not include any <script> tags and there is no SystemJS configuration either. Is this the expected behavior? I was anticipating the CLI ...