Configuring a Loading Bar for Angular 9 Application

A guide on how to add a loading bar to the JHipster-generated Angular 9 web application:
As every seasoned Web developer is painfully aware, web applications tend to behave “slightly” differently once deployed to the target server environment.
Our new super coll web app, which had ninja time instant responses while running in a local dev environment (on localhost), once deployed to the server, becomes subject to network lags, glitches in the infrastructure, failures of other systems that it depends on and so forth.
Medium lKeeping users informed that something is happening and that system is busy executing their actions is one of the main principles of good user interface design. Loading or progress bars have proven to be very effective tools of communication to the app users that their action has been received and that system is busy performing it.
In this blog post we will demonstrate how to add a loading bar to the JHipster generated Angular 9 web application. In the previous blog post, we generated JHipster/Angular version of the famous Spring Petclinic application, we will use this app as a playground for this tutorial to demonstrate how to improve user experience with the use of ngx-loading-bar library. For more details on ngx-loading-bar see the project’s web site.
If you would like to follow this article “hands on,” you can do that by cloning the jhpetclinic repository (if you haven’t done it yet) and switching to the progres_bar_start branch. This branch represents the starting point for this tutorial. To do so execute the following two git commands:
git clone https://github.com/dmadunic/jhpetclinic.git
git checkout progress_bar_start
Register and Configure ngx-loading-bar router and HTTP-client modules
The first step is to add the required dependencies to the project. In that order, inside the project root folder execute the following commands:
npm install @ngx-loading-bar/core @ngx-loading-bar/http-client @ngx-loading-bar/router --save
With npm packages in place, now it is time to configure JHpetclinic app to use it. The first thing we will do is to configure loading bar to be shown at the top of the browser window area every time a user navigates to another page. Locate the app.module.ts file and add the following lines to it:
…
// 1. import ngx-loading-bar modules
import { LoadingBarModule } from ‘@ngx-loading-bar/core’;
import { LoadingBarRouterModule } from ‘@ngx-loading-bar/router’;
@NgModule({
imports: [
BrowserModule,
JhpetclinicSharedModule,
JhpetclinicCoreModule,
JhpetclinicHomeModule,
// jhipster-needle-angular-add-module JHipster will add new module here
JhpetclinicEntityModule,
JhpetclinicAppRoutingModule,
// 2. register ngx-loading-bar modules
LoadingBarModule,
LoadingBarRouterModule
],
declarations: [MainComponent, NavbarComponent, ErrorComponent, PageRibbonComponent, ActiveMenuDirective, FooterComponent],
bootstrap: [MainComponent],
})
export class JhpetclinicAppModule {}
Now navigate to: src/main/webapp/app/layouts/main, open main.component.html file and add the following line to it:
<jhi-page-ribbon></jhi-page-ribbon>
<div>
<router-outlet name="navbar"></router-outlet>
</div>
<!-- Add ngx-loading-bar at the top ot the display area -->
<ngx-loading-bar color="#CD67BA" height="4px"></ngx-loading-bar>
<div class="container-fluid">
<div class="card jh-card">
<router-outlet></router-outlet>
</div>
<jhi-footer></jhi-footer>
</div>
If you start the JHPetclinic app now you will see nice loading bar and the spinner at the top of the window area every time you navigate to a new page (as in the image bellow).

ngx-loading-bar offers several configuration options, for example turning spinner off and on, adjusting the color of the bar, and so on. We will not dive into those here, but feel free to check the official docs for more details.
Contact

Looking for agile software development experts?
With this we have taken care of user’s navigation through our app. Now, its time to turn our attention to a little more complicated task, that is of displaying a progress bar when our application is waiting for a response from server to begin navigation to another page.
To demonstrate this case perform the following:
- Import jhpetclinic into your favorite IDE (ie. IntelliJ or Eclipse)
- Run jhpetclinic in debug mode and put the break point to the second line of the org.jhipster.petclinic.web.rest.UserJWTController.authorize()method as shown on the picture bellow

Now in the separate terminal window, inside the jhpetclinic root folder start the angular client app:
npm start
If you attempt to “Sign in” into app now, you will notice that nothing is happening (since we have stopped the process on the server side with the breakpoint). The LoadingBarRouterModule handles only transitions from page to page, yet no transition is happening at the moment, our application is waiting for the data from server.
However, our users are left with no indication that anything is happening and would simply (impatiently) had to wait for an HTTP request to time out to receive any response from our app—needless to say, very undesired behavior.
Fortunately, there is a simple way to fix this, all we have to do is configure @ngx-loading-bar/http-client library in our application. Similar to the behavior of the router module, registered LoadingBarHttpClientModulewill attach itself to every HTTP request, and trigger display of progress bar while the operation is in progress. To achieve this, first add the npm package, by executing (inside the project root folder):
npm install @ngx-loading-bar/http-client --save
Now import LoadingBarHttpClientModule, by modifying app.module.tsfile so that it looks as in the code snippet bellow:
...
// 1. import ngx-loading-bar modules
import { LoadingBarModule } from '@ngx-loading-bar/core';
import { LoadingBarHttpClientModule } from '@ngx-loading-bar/http-client';
import { LoadingBarRouterModule } from '@ngx-loading-bar/router';
@NgModule({
imports: [
BrowserModule,
JhpetclinicSharedModule,
JhpetclinicCoreModule,
JhpetclinicHomeModule,
// jhipster-needle-angular-add-module JHipster will add new module here
JhpetclinicEntityModule,
JhpetclinicAppRoutingModule,
// 2. register ngx-loading-bar modules
LoadingBarModule,
LoadingBarHttpClientModule,
LoadingBarRouterModule
],
declarations: [MainComponent, NavbarComponent, ErrorComponent, PageRibbonComponent, ActiveMenuDirective, FooterComponent],
bootstrap: [MainComponent],
})
export class JhpetclinicAppModule {}
Finally lets also add some modification in the src/main/webapp/app/layouts/main/mainn.component.html file, one as displayed in the code snippet bellow.
<jhi-page-ribbon></jhi-page-ribbon>
<div>
<router-outlet name="navbar"></router-outlet>
</div>
<!-- Add ngx-loading-bar at the top ot the display area -->
<ngx-loading-bar color="#CD67BA" height="4px" [includeSpinner]="false" ref="router"></ngx-loading-bar>
<ngx-loading-bar color="#CD67BA" height="4px" ref="http"></ngx-loading-bar>
<div class="container-fluid">
<div class="card jh-card">
<router-outlet></router-outlet>
</div>
<jhi-footer></jhi-footer>
</div>
With these changes, we have configured two loading bars. You can see them (overlapping) at the top of the browser window area.
- The first loading bar will be used by the router module and will display a 4-pixel thick loading bar every time we navigate from page to page.
- The second loading bar will be used by the HTTP-client module and will display both the loading bar and the spinner every time an application performs an HTTP request to the server.
This way, based on the behavior of the loading bar component, we can be aware of what our application is waiting for, is there a problem with the client angular code and transition from state to state or with the server API we are invoking. To test it, you can now repeat the small exercise from above. If all is well, you should see the loading bar and the spinner while the Angular app is waiting for a release breakpoint.
What next?
In case you need more control over the LoadingBar please check the official docs on how to manually start and stop loading bar inside a service.
Sample Code:
The entire source code for this tutorial is available in GitHub repository.