Angular Material Display Spinner with Every HTTP Request
Angular Show Spinner with Every HTTP Request

Angular Material Display Spinner with Every HTTP Request

It is an essential requirement for any application to show some kind of a loading animation – Angular apps are no exception. We often make HTTP requests to communicate with a back-end API. In this post, we will implement an abstract solution to show an Angular Material spinner while an HTTP request is taking place using a custom HTTP interceptor.

Although this tutorial uses the material library, you can easily use any other loading indicator component with this solution.

Here is a list of steps we’re going to follow:

  • Create an HTTP Interceptor to detect when a request has started/ended.
  • Create a shared Angular service to inform the components about the status of the request.
  • Use the service in components to show and hide angular material spinner in the user interface.

Demonstration of Angular Material spinner component:

Angular Material Spinner

Create a New Project

The first step is to create a new Angular project and add Material library references.

If you already have a project, you can skip this step.

Otherwise, check out this guide to setup a new project with Angular Material components.

Create a Spinner Service

Create a new file called `SpinnerService` and paste the following code:

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

  providedIn: 'root'
export class SpinnerService {

  visibility: BehaviorSubject<boolean>;

  constructor() {
    this.visibility = new BehaviorSubject(false);

  show() {;

  hide() {;

This is a very simple service that is responsible for storing the visibility status of the loader. It also broadcasts the status change to all subscribers. Subscribers are components and classes that subscribe to the visibility event of this service.

When the visibility value changes, all other listeners will be notified of this change. Through data binding in Angular, we can bind the visibility of the spinner component to the visibility value of this service.

Bind the Spinner to the Service

The ideal place for putting the spinner component is usually the layout component. For the purpose of this tutorial, I am simply placing the spinner in the app.component.html file.

<mat-spinner [diameter]="50" *ngIf="showSpinner"></mat-spinner>

<button mat-raised-button color="primary" (click)="doWork()">Do Work</button>

As you can see, the visibility of the spinner above is bound to the showSpinner variable.

I have added a button to make a simple HTTP request so that we can see the spinner during the request.

The component has a spinner, whose visibility is controlled with an ngIf, bound to the value from the service with an async pipe. This ensures that the variable value is always in sync with the service variable.

Inject the SpinnerService into the constructor of the app component.

Update the html to subscribe to the service:

import { Component, OnInit } from '@angular/core';
import { SpinnerService } from './spinner.service';
import { HttpClient } from '@angular/common/http';

  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
export class AppComponent implements OnInit{
  showSpinner: boolean;

  constructor(private spinnerService: SpinnerService,
    private httpClient: HttpClient) { }

  ngOnInit() {

  doWork() {
    // Make a get request
        success => {
        error => {
<mat-progress-bar color="accent" mode="indeterminate" *ngIf="spinnerService.visibility | async"></mat-progress-bar>

With the shared service and the component logic, all we need to do now is detect HTTP requests with an HTTP interceptor and update the visibility value.

Create a Custom HTTP Interceptor

Angular 4.3 introduced HttpInterceptor, which provides a way to intercept HTTP requests and responses to transform or handle them before executing them.

We will use a custom HTTP interceptor to display the loader before making the request and hide it when the request is finalised.

Create a new file called http-interceptor.ts and paste the following code:

import { Observable } from 'rxjs';
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpResponse } from '@angular/common/http';
import { HttpRequest } from '@angular/common/http';
import { HttpHandler } from '@angular/common/http';
import { HttpEvent } from '@angular/common/http';
import { tap } from 'rxjs/operators';
import { SpinnerService } from './spinner.service';

export class CustomHttpInterceptor implements HttpInterceptor {

     constructor(private spinnerService: SpinnerService) { }

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {;

        return next
                tap((event: HttpEvent<any>) => {
                    if (event instanceof HttpResponse) {
                }, (error) => {

It is apparent that the above class implements the intercept method of HttpInterceptor from @angular/common/http.

The implementation grabs the current request and subscribes to the response. There are so many things that we can do at the time we grab the request, such as injecting a token for the purpose of authentication.

In our case, we just want to show a loader before passing on the request and hide it when the response comes back.

Tell Angular to Use the Custom Interceptor

We must now provide the custom interceptor in the providers array of the app.module.ts so that Angular knows how to intercept requests.

import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { CustomMaterialModule } from './custom-material/custom-material.module';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { CustomHttpInterceptor } from './http-interceptor';

  declarations: [
  imports: [
  providers: [{
    useClass: CustomHttpInterceptor,
    multi: true
  bootstrap: [AppComponent]
export class AppModule { }


In this post, we implemented an abstract solution to display an Angular Material spinner component during an HTTP request using a custom interceptor.

Umut Esen

Umut is a certified Microsoft Certified Solutions Developer and has an MSc in Computer Science. He is currently working as a senior software developer for Royal London. He is the primary author and the founder of onthecode.

This Post Has 3 Comments

  1. Ale

    But using this interceptor, the other request that I had at the app does not work anymore. How can I to get this interceptor to work only to show/hide the spinner?

    1. Umut Esen
      Umut Esen

      The order of interceptors matter, so ensure you add the spinner interceptor last with multi flag set to true.

  2. Ajay Saini

    Thank you. It is really a nice article.

Leave a Reply