Tue. Apr 23rd, 2024

Just about every project I need to have at least one loading spinner to indicate to the user that data is being loaded and to wait. My recent project I found that to be no exception. I wanted to come up with something that I thought was a little nicer than what I have used in the past.

To give credit where credit is due this was inspired by @divyamember with this stackblitz. Here is my take:

import {Injectable, TemplateRef, ViewContainerRef} from '@angular/core';
import {Overlay, OverlayRef, PositionStrategy} from "@angular/cdk/overlay";
import {TemplatePortal} from "@angular/cdk/portal";

  providedIn: 'root'
export class OverlayService {
      private overlay: Overlay
  ) { }
  createOverlay(config: any): OverlayRef {
    return this.overlay.create(config);
  attachTemplatePortal(overlay: OverlayRef, template: TemplateRef<any>, view: ViewContainerRef) {
    let templatePortal = new TemplatePortal(template, view);

  positionGloballyCenter(): PositionStrategy {
    return this.overlay.position()

My OverlayService, with not real significant changes. Three methods used to setup the overlay.

import {Component, DoCheck, Input, OnInit, TemplateRef, ViewChild, ViewContainerRef} from '@angular/core';
import {OverlayService} from "../../services/overlay.service";
import {OverlayRef} from "@angular/cdk/overlay";

  selector: 'app-loading-spinner',
  templateUrl: './loading-spinner.component.html',
  styleUrls: ['./loading-spinner.component.scss']
export class LoadingSpinnerComponent implements OnInit,DoCheck {
  @Input("loading") loading: boolean = true;
  @Input("message") message: string = '';
  @ViewChild('spinnerRef') private spinnerRef: TemplateRef<any>;

  config:any ={};
  private overlay: OverlayRef;

  constructor(private vcRef: ViewContainerRef, private overlayService: OverlayService) { }

  ngOnInit(): void {
    this.config = {
      hasBackdrop: true,
      positionStrategy: this.overlayService.positionGloballyCenter()

    this.overlay = this.overlayService.createOverlay(this.config);

  ngDoCheck(): void {
    if (this.loading && !this.overlay.hasAttached() && this.spinnerRef != undefined) {
      this.overlayService.attachTemplatePortal(this.overlay, this.spinnerRef, this.vcRef);
    } else if (!this.loading && this.overlay.hasAttached()) {

Here is my code for my component. Now I removed many of the inputs, and broke this down to just what I needed. An input to indicate if we are still loading, and the message to indicate what we are doing.

.center-content {

This is my scss to center the content in my HTML.

<ng-template #spinnerRef>
        <mat-card-content class="center-content">
            <mat-spinner [color]="'warn'">


This will allow the user to see the page as it is built, but keep them from interacting with it until it has completed loading, while showing a nicely formatted mat-card with a spinner that the application is loading.

<app-loading-spinner [loading]="true" message="Loading Data">
    <p>Waiting for data to load</p>

Simple usage your wrapped HTML will be loaded, and a Spinner with message “Loading Data”

By Jeffery Miller

I am known for being able to quickly decipher difficult problems to assist development teams in producing a solution. I have been called upon to be the Team Lead for multiple large-scale projects. I have a keen interest in learning new technologies, always ready for a new challenge.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.