Published in



An Angular service to manage loading state indicators

Creating a reusable and effective service to manage visual responses to user interaction

If you’ve built an angular app or two, you’ve likely implemented async services such as a REST API. When your user interacts with your app and triggers an async event, they need to know what's happening. So you create loading spinners, status messages and conditional logic to go with it. This can get repetitive, frustrating, and isn’t maintainable.

Using a service to handle the logic that responds to events triggered by UI, or any other emitter, can save you a lot of repetition and provide consistency through your application.

The purpose of this service is:

  • To create a state object for events that enables control of visual elements and messages
  • Provide functions to manage this state
  • Provide observables for sharing state between components

This article presents an example of such a service. It manages state objects that provide parameters and methods for consumers to use to render information to the user. It includes reactive programming to aid in sharing information between components.

Essential Services make the world go round, and Angular apps to. (Photo M.Raju)

To add the completed service and start using it now, run this command in your project:npm i @bit/mxds.angular-components.async-ui-feedback-module . Read on to understand it’s construction, or, get ideas on how to implement your own version.

Sidenote: If you haven’t started using bit yet, you should. It makes your code instantly reusable, easily maintainable and can be set up in minutes. Read this article to get going.

The implementation was broken down into 3 key parts: State Interface, Event Class, and the Service. Click here to view the full code for the service.

State Interface

export interface AsyncUIState {   
id: number;
loading: boolean;
error: boolean;
complete: boolean;
errMessage?: string;
successMessage?: string;

This is the data that components will use to render spinners, text buttons etc… depending on the current values of an instance implementing this interface.

Event Class

This class provides functions that control the state, presents parameters for components to use and includes an observable of the current state. It’s to big for this article, so click here to read the AsyncUIEvent code.

An Event Class object is instantiated by the service every time it needs to manage a new event. This event is then held in the component for use, as well as in an array in the service.

Parameters passed to the construction of an Event can allow the reactive(Observable) features to be turned off, and, an instance of MatSnackBar can be passed in to enable the Event to open snack bars on completion or error.

start(), complete(), error() and reset() can all be called on the event to set the appropriate flags/messages on the State. All of these methods then emit the state through the state$ Observable.

The service

This is a singleton service, provided in root. It creates, gets and deletes Events. It also holds an Observable of all the existing Events. This observable emits every time anevent.state$ emits a value.

The delete function removes existing subscriptions for the event and should be used to avoid any performance issues. See the full code for the service here.

Putting it all together

With the interface, the Event class and the service ready to go, you can now implement this service in your components. You can review this component code for an example implementation.

Hopefully, the example code provided here has given you the ideas need to implement a similar service of your own. If you have any feedback or questions, drop a comment.

You can download and implement the service in this article by calling npm i @bit/mxds.angular-components.async-uifeedback and adding the following to the module using the service:

import { AsyncUIFeedbackService } from '@bit/mxds.angular-components.async-uifeedback';import { MatSnackBarModule } from '@angular/material/snack-bar';@NgModule({
declarations: [AsyncUIExampleComponent],
imports: [
providers: [AsyncUIFeedbackService]
export class ExampleModule { }



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store