Two Simple Ways to Implement Loading Spinners in Angular

Two Simple Ways to Implement Loading Spinners in Angular

Sunny Sun Lv4

This post was update on 29-07-2024

Loading spinners are essential for creating a smooth user experience. When users trigger actions that require time, like fetching data from a server, a loading spinner provides visual feedback, indicating that the application is actively working. This small but crucial element helps manage user expectations and prevents frustration.

By showing users that the application is responsive and processing their request, loading spinners significantly improve perceived performance.

This article will discuss two ways to show a spinner in an Angular app: an overlay and a template.

Use global interceptor

Angular Interceptors provide a powerful mechanism to intercept and modify HTTP requests and responses globally within an application. Think of them as guardians of your network traffic, allowing you to perform actions before or after a request is sent. This centralized approach promotes code reusability and maintainability.

To show a loading spinner, we can use interceptor and an overlay. An overlay is a transparent container that is displayed on top of the existing content and covers the entire screen. It is commonly used to block users from interacting with the page.

Firstly, let’s create a SpinnerService.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Injectable({  
providedIn: 'root',
})
export class SpinnerService {
public loading$: Observable<boolean>;
private _loading$: BehaviorSubject<boolean> = new BehaviorSubject(false);

public constructor() {
this.loading$ = this._loading$.asObservable();
}

set(loading: boolean) {
this._loading$.next(loading);
}
}

In the SpinnerService, we created private property _loading$ as BehaviorSubject, which allows it to emit the current value to new subscribers and keep track of the last emitted value. The service exposes the following

  • observable loading$ , which can be subscribed to.
  • Set method to allow the mutation of the loading state.

Next, we can create the spinner component using the material spinner.

1
2
3
4
5
6
7
8
9
10
11
<div *ngIf="isLoading$ | async" class="main-container">  
<div class="loading-container">
<mat-spinner color="warn"></mat-spinner>
</div>
</div>

// Component class
export class OverlaySpinnerComponent{
isLoading$ = this.spinnerService.loading$;
constructor(public spinnerService: SpinnerService) {}
}

The component template contains a Material Design spinner element <mat-spinner> with the color warn. In the component class, we defined a property isLoading$ that is being assigned the value of the loading$ property from the spinnerService. This service is being injected in the constructor, and it’s used to keep track of the loading state of the application.

We can use CSS to format the spinner component to create an overlay in Angular.

1
2
3
4
5
6
7
8
9
10
11
12
.loading-container {  
position: absolute;
top: 0;
left: 0;
bottom: 56px;
right: 0;
background: rgba(0, 0, 0, 0.15);
z-index: 99;
display: flex;
align-items: center;
justify-content: center;
}

The key to this approach is the interceptor. The ApiInterceptor service intercepts all HTTP requests and responses and sets the loading state to true before the request is sent, and sets it to false when the response is received via the SpinnerService. This allows us to show and hide the loading spinner based on the state of the application’s HTTP requests.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Injectable()  
export class ApiInterceptor implements HttpInterceptor {
constructor(private spinnerService: SpinnerService) {}

intercept(
request: HttpRequest<unknown>,
next: HttpHandler
): Observable<HttpEvent<unknown>> {
this.spinnerService.set(true);
return next.handle(request).pipe(
finalize(() => {
this.spinnerService.set(false);
})
);
}
}

The interceptor service needs to be registered in AppModule to be effective.

1
2
3
4
5
6
7
8
//app.module.ts    
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: ApiInterceptor,
multi: true,
},
]

Finally, we are ready to consume the newly created spinner.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div>  
<button (click)="load()">Click here to show overlay spinner</button>
<app-overlay-spinner></app-overlay-spinner>
</div>
// OverlayDemoComponent
export class OverlayDemoComponent{
public data: any;
constructor(private apiService: ApiService) {}

load() {
this.apiService.getData().subscribe((data) => {
this.data = data;
});
}
}

The loading spinner will be shown when the API call is triggered.

overlayer spinner

Template-based spinner

Another approach to showing a loading spinner in Angular is by using a template. A template is a piece of HTML that is rendered within a component or directive.

Angular template

An Angular template is a fundamental building block of an Angular application, defining the structure and layout of the user interface. Templates are written in HTML and can include Angular-specific syntax and directives to display dynamic data, handle user input, and control the rendering of elements. By binding data and logic to the UI, templates enable developers to create responsive and interactive applications. Angular templates can also incorporate components, pipes, and custom directives, making them a powerful tool for building complex and scalable web applications.

To create a template for the loading spinner, the ng-template directive defines a template, and the *ngIf directive is to show or hide the template based on a boolean value.

Here is an example of using a template for the loading spinner.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<div>  
<button (click)="load()">Click here to show spinner</button>
<app-loading-spinner *ngIf="loading$ | async; else contentBlock"></app-loading-spinner>
<ng-template #contentBlock>
<div>
<h4>Content loaded</h4>
</div>
</ng-template>
</div>

// LoadingSpinnerDemoComponent
export class LoadingSpinnerDemoComponent{
loading$ = new BehaviorSubject<boolean>(false);

load() {
// simulate a service call
this.loading$.next(true);
setTimeout(() => {
this.loading$.next(false);
}, 3000);
}
}

The LoadingSpinnerDemoComponent class contains a loading$ observable to display and hide the loading spinner. The method load() is used to simulate a service call and updates the value of the loading$.

In the LoadingSpinnerDemoComponent template, we use an app-loading-spinner component to show the spinner. We can continue to use the Material spinner or use other methods, including font-awesome or custom CSS. Below are a couple of examples.

1
2
3
4
5
6
7
8
9
10
<!-- material design spinner -->  
<div style="display: flex; justify-content: center">
<mat-spinner color="info"></mat-spinner>
</div>
<!-- fontawesome style -->
<div style="display: flex; justify-content: center">
<div class="fa fa-spinner fa-spin fa-3x fa-fw margin-bottom" style="line-height: 100px"></div>
<div class="fa fa-refresh fa-spin fa-3x fa-fw margin-bottom" style="line-height: 100px"></div>
<div class="fa fa-cog fa-spin fa-3x fa-fw margin-bottom" style="line-height: 100px"></div>
</div>

The spinner will look like this

template based spinner

The template-based method is my preferred approach. It is simple and flexible, allowing you to show and hide a section or entire page.

conclusion

We’ve covered two foundational methods for displaying loading spinners in Angular: overlays and templates. But your options extend far beyond these! Let’s explore the exciting world of spinner implementation:

  • Third-party libraries: Leverage pre-built libraries with rich features and animations.
  • Custom directives: Craft reusable components tailored to your specific needs.

The ideal approach depends on your project’s requirements and desired aesthetics. Don’t hesitate to experiment and find the perfect fit!

For a hands-on dive, explore the sample code provided in this article: here . It showcases both overlay and template implementations, giving you a solid foundation to build upon.

  • Title: Two Simple Ways to Implement Loading Spinners in Angular
  • Author: Sunny Sun
  • Created at : 2023-01-25 00:00:00
  • Updated at : 2024-07-29 19:08:51
  • Link: http://coffeethinkcode.com/2023/01/25/two-simple-ways-to-loading-spinners-angular/
  • License: This work is licensed under CC BY-NC-SA 4.0.
On this page
Two Simple Ways to Implement Loading Spinners in Angular