Contents
1. Introduction
Loading is essential in a website, it can let the user know the flow is processing, otherwise user will not know what’s happening. So, I will introduce an excellent loading package to help you solve the loading issue!
2. ngx-loading
ngx-loading
is a very nice and customizable loading spinner for Angular, there are flexible config options that let you setup different loading styles. You can install ngx-loading with the below command
npm install --save ngx-loading
And you can find the base usage in github
3. Use in the common layout
With normal usage, you need to add the below code in each html
page, so in this article, I will show you how to use the ngx-loading
in a common layout.
<ngx-loading
[show]="loading"
[config]="{ backdropBorderRadius: '3px' }"
[template]="customLoadingTemplate"
></ngx-loading>
3.1. Create the service
The concept is we will put the ngx-loading
in the common (or parent) page’s HTML
layout, so we can’t control it in the child page directly, the solution is we can use a Subject
.
The Subject
is a special type of Observable that allows values to be multicasted to many Observers. Subjects are like EventEmitters
.
So we can create a service to handle the Subject
. Suppose we just need to control start
and stop
to show the loading in needs, so create these two methods in the service, and don’t forget to release the object, the complete code as below:
import { Injectable, OnDestroy } from "@angular/core";
import { Subject } from "rxjs";
@Injectable({
providedIn: 'root',
})
export class LoadingService implements OnDestroy {
// Observable string sources
private emitChangeSource = new Subject<boolean>();
// Observable string streams
changeEmitted$ = this.emitChangeSource.asObservable();
// Start loading
start() {
this.emitChangeSource.next(true);
}
// Stop loading
stop() {
this.emitChangeSource.next(false);
}
ngOnDestroy() {
// complete and release the subject
this.emitChangeSource.complete();
}
}
3.2. Add the ngx-loading to the layout
1) Import the NgxLoadingModule
in your root app module
import { BrowserModule } from "@angular/platform-browser";
import { NgModule } from "@angular/core";
import { CoreModule } from "./core/core.module";
import { NgxLoadingModule } from "ngx-loading";
@NgModule({
//...
imports: [
//...
NgxLoadingModule.forRoot({}),
],
//...
})
export class AppModule {}
2) Create a loading
flag and config in the main layout backend(.ts) file
const PrimaryRed = '#dd0031';
const SecondaryBlue = '#1976d2';
//...
//set the loading flag
loading = false;
//set the loading config
//reference: https://github.com/Zak-C/ngx-loading#config-options
config = {
animationType: ngxLoadingAnimationTypes.threeBounce,
primaryColour: PrimaryRed,
secondaryColour: SecondaryBlue,
tertiaryColour: PrimaryRed,
backdropBorderRadius: '3px',
};
3) Subscribe and update the loading status in the main layout
// Update loading status
this.loadingService.changeEmitted$.subscribe(isLoading => {
//console.log(isLoading);
this.loading = isLoading;
});
4) Add the loading HTML code in the main layout frontend(.html) file
<ngx-loading #ngxLoading [show]="loading" [config]="config" [template]="loadingTemplate"></ngx-loading>
<ng-template #loadingTemplate>
<div class="loading-class">
<h4>Please wait ...</h4>
</div>
</ng-template>
Ok, now, we just need to control the loading flag in other child pages with LoadingService
4. Usage in child pages
We still using this code for the demo. Apply the loading when doing login, so we set the private loadingService: LoadingService
in the login component’s constructor, and call this.loadingService.start();
after submitting the login form, and then call this.loadingService.stop();
when success or failed login:
constructor(//...
private loadingService: LoadingService) {
}
//login
login() {
//start the loading
this.loadingService.start();
this.auth
.login(this.username.value, this.password.value)
.pipe(filter(authenticated => authenticated))
.subscribe(
() => {
console.log('after logined and redirect');
//stop the loading
this.loadingService.stop();
this.router.navigateByUrl('/user-management');
},
(errorRes: HttpErrorResponse) => {
//stop the loading
this.loadingService.stop();
if(errorRes.status == 401){
//...
}
console.log('Error', errorRes);
}
);
}
After clicking the login button, it will show the loading as below
5. Conclusion
If we want to control the parent component in the child, we need to subscribe to the change status and update it in the child, so we can use the Subject
and create a service for that! This is the same concept as this article to use the SweetAlert2
in angular.