1

Inspired from the SO answer - Show loading screen when navigating between routes in Angular 2, I want to show a progress bar before the main page of my Angular application uploads. But it isn't working.

I have created a progress component with selector app-progress-bar'. Its HTML is

progress.component.html

<div class="loading-overlay" >
  <!-- show something fancy here, here with Angular 2 Material's loading bar or circle -->
  <mat-progress-bar mode="indeterminate"></mat-progress-bar>
</div>

My app component uses css-grid having 3 rows and 1 column. The HTML is

app.component.html

<div class="body__div--background"  >
  <div class="css-grid-container"  *ngIf="loading">
    <app-progress-bar></app-progress-bar>
  </div>
  <div class="css-grid-container" *ngIf="!loading">
    <app-nav-component></app-nav-component>
    <!-- the components which target this router-outlet could be containers. Don't make this content-component a container-->
    <app-content-component></app-content-component>

    <!--app-content-component></app-content-component> <!--this component has router-outlet to put new componnents in it -->
    <app-footer-component></app-footer-component>
  </div>

</div>

The css to position the above layouts is

app.component.css

.body__div--background {
  background: linear-gradient(45deg,#33b1f8 37%,#6e90f6 100%); /*syntax linear-gradient(direction, color1 limit, color2 limit)*/
  color:#555555;
  font-family: Helvetica;
  line-height:1.5;
  font-size: 11px;
  letter-spacing: 0.25px;
}

.css-grid-container{
  height:100vh; /*height of the container is same ahs height of the view port.*/
  display: grid;
  grid-gap:20px;
  grid-template-columns: 1fr;  /* 1 columns*/
  grid-template-rows: auto 15fr 1fr; /* 3 rows. Auto takes height of navigation, remaining is divided into 2 rows, middle row is 15 times larger than the 3rd row.*/
}

app-nav-component {
  grid-column: 1 / -1;
  grid-row: 1 / 2;
}

app-content-component{
  grid-column: 1 / -1;
  grid-row: 2 / 3;
}

app-footer-component{
  grid-column: 1 / -1;
  grid-row: 3 / -1;
}

app-progress-bar{
  grid-column: 1 / -1;
  grid-row: 1 / -1;
}

and the .ts file is

app.component.ts

import { Component } from '@angular/core';
import * as moment from "moment";
import {MatProgressBarModule} from '@angular/material/progress-bar';

import {
  Router,
  // import as RouterEvent to avoid confusion with the DOM Event
  Event as RouterEvent,
  NavigationStart,
  NavigationEnd,
  NavigationCancel,
  NavigationError
} from '@angular/router'

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'app';
  // Sets initial value to true to show loading spinner on first load
  loading = true

  constructor(private router: Router) {
    router.events.subscribe((event: RouterEvent) => {
      this.navigationInterceptor(event)
    })
  }

  // Shows and hides the loading spinner during RouterEvent changes
  navigationInterceptor(event: RouterEvent): void {
    console.log("received event from Router:",event)
    if (event instanceof NavigationStart) {
      console.log("NavigationStart")
      console.log("old load"+this.loading)
      this.loading = true
      console.log("new load"+this.loading)
    }
    if (event instanceof NavigationEnd) {
      console.log("NavigationEnd")
      console.log("old load"+this.loading)
      this.loading = false
      console.log("new load"+this.loading)
    }

    // Set loading state to false in both of the below events to hide the spinner in case a request fails
    if (event instanceof NavigationCancel) {
      console.log("NavigationCancel")
      console.log("old load"+this.loading)
      this.loading = false
      console.log("new load"+this.loading)
    }
    if (event instanceof NavigationError) {
      console.log("NavigationError")
      console.log("old load"+this.loading)
      this.loading = false
      console.log("new load"+this.loading)
    }
  }

}

I am using the above component in main.html

<app-root>Loading ...</app-root>

All I see is the message Loading ... and then my page loads but I don't see the progress bar. How could I show a progress bar or a spinner while Angular loads up the application?

Manu Chadha
  • 15,555
  • 19
  • 91
  • 184

1 Answers1

0

you can use the below code for reference but change the move function according to your requirements:

<!DOCTYPE html>
<html>
<style>
#myProgress {
  width: 100%;
  background-color: #ddd;
}

#myBar {
  width: 1%;
  height: 30px;
  background-color: #4CAF50;
}
</style>
<body>

<h1>JavaScript Progress Bar</h1>

<div id="myProgress">
  <div id="myBar"></div>
</div>

<br>
<button onclick="move()">Click Me</button> 

<script>
function move() {
  var elem = document.getElementById("myBar");   
  var width = 1;
  var id = setInterval(frame, 10);
  function frame() {
    if (width >= 100) {
      clearInterval(id);
    } else {
      width++; 
      elem.style.width = width + '%'; 
    }
  }
}
</script>

</body>
</html>
Nikhil S
  • 3,786
  • 4
  • 18
  • 32
  • Thanks. I suppose what I was trying to achieve isn't possible. I want to show a progress bar while angular loads but the logic of displaying the progress bar is in angular itself. So I'll never get to see the progress bar. I just read this article. The logic of displaying a progress bar has to be in the index.html which hosts the main angular component and not in angular itself - https://medium.com/@tomastrajan/how-to-style-angular-application-loading-with-angular-cli-like-a-boss-cdd4f5358554 – Manu Chadha May 24 '18 at 21:45