Add loading To UI element in Angular like a pro.

shahid ahmad bangash
ngBangash
Published in
3 min readSep 19, 2020

--

I just want to share my experience by showing the loader on the web app, when HTTP requests or any async processes are calling.

Last month our UI/UX team decided to show the loader on the button instead of showing a progress bar on top of the page and also our QA team reported bugs about preventing the users from the double click.

The following problems need to be resolved.

  1. Restrict the user from the double click.
  2. show some state on UI (Button) element so the user knows the button is pressed like the loader or changes the color.
  3. handling multiple buttons on the same view.
  4. if the request succeeded than make a UI element green otherwise make it red for error.

In the current project, we have hundreds of components, and each component may have multiple action buttons.

None Angular way (a common approach)

  1. Declare a boolean state ‘loading’ in a component.
  2. Make it ‘true’ when the user ‘click’.
  3. Make it ‘false’ once the request becomes successful or throw an error.
  4. Attach this boolean to the UI element to show the loader and disable the button to avoid users from the double click.

up to now we just resolve the first and second problems. what about the third and fourth.

The Third problem, we just take the numbers of booleans as we have a number of action buttons on the view.

The fourth problem can be handle by assigning a different class name and then interpolation to class attribute on the element. like

loading.component.ts
loading.component.html

it’s very painful to do this when you have hundreds of components and you need to do this, one thing more if you have multiple buttons in the same component, you want to create a separate state for each.

Using the power 💪 of Angular Directives.

There are a few issues in the above solution. Like

  1. Repetition of code.
  2. No separation of concern.
  3. Need to add testing in each component.

For this purpose, we are going to use the power angular directive.

let’s create a simple directive.

We make reference to the current element by injecting ELementRef. once we have a reference then we can easily add a class by native API (classList) and by hostListener we listen to the click on the button and add ‘active’ class, after 3-second add ‘success’ class and remove the ‘active’ class. here is a stackblitz-part-1.

in a real scenario, we are calling the backend API which takes different amounts of time, not exactly 3-second.so we need to watch for real async request, in angular, we mostly handle async request through observable(httpClient also return observable).

for the exact amount of time calculation, we need to pass observable and subscribe to it in the directive.

loading.component.html
loading.component.ts

you can control side effects (navigation, show toaster) in tap and error in catchError. stackblitz part 2.

Wait, wait, our feature is not yet completed, we need to make it flexible because there are so many things to do like, consumers of directive want to do something before calling API service, etc.

  1. validate the form.
  2. pass data to login function.
  3. transform form data.
  4. show some confirmation dialog.

so how we can do this 🤔.let’s move further.

Inversion of Control.

Instead of only passing observable to the directive, we need to give full control to the consumer to passing function to the directive and the function should return observable. let’s see in action.

loading.directive.ts
loading.component.ts
loading.component.html

we returning observable from the function so need to subscribe at in the directive.

In HTML, we need to use ‘bind’ to bind the context of ‘this’ to the current component otherwise it will use the context of the directive.

you can add error class by explicitly throw an error in function like in case of an invalid form .we take care of it by wrap the function call at in try-catch.

I created the npm plugin. also, I created the NGXS version of this plugin.

Follow me on Medium or Twitter to read more about Angular, NGXS, Javascript.

--

--

shahid ahmad bangash
ngBangash

I’m a Frontend Engineer at SMSAMI.inc, open source maintainer and contributor, blogger.