Reputation: 1592
I have an Angular project where I am extensively using the Angular Material library. I would like to use the Progress Bar Component to show when a page is loading or when I make an api call. For example, while I'm waiting for a response from Stripe.
Starting the progress bar seems simple, just use a global variable in a service to signal when the page is loading. I'm thinking of using the router for that.
However, I would like to show the actual progress of the page load. An example would be when you go to a youtube video. The component api uses a value property to display the amount of progress. But how to get the progress of the page load?
I know there are other libraries such as ngx that use this but I would like to use the Angular Material library if possible.
Any ideas how to achieve this?
Upvotes: 2
Views: 6545
Reputation: 855
Too late but maybe someone else needs it:
There are packages for this, for example ng2-slim-loading-bar.
But if you want to do it manually with Material Progress Bar then take a look at this example.
It really gives a false illusion of progress because it increases over time, and in case it reaches 95% without the load being finished then it stops until that happens. I don't know if there is any way to calculate the true progress of a request, that would be perfect.
Edit: Check Angular docs about Tracking and showing request progress, with that you may be able to implement a fairly real progress bar.
Component:
import { Component } from '@angular/core';
import {
NavigationCancel,
Event,
NavigationEnd,
NavigationError,
NavigationStart,
Router,
} from '@angular/router';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
})
export class AppComponent {
progressValue = 0;
progressColor = 'primary';
progressTimer: number;
// This will be used to force stop (if an error occurs, or the user stops loading)
stopProgress = false;
constructor(private router: Router) {
this.router.events.subscribe((event: Event) => {
this.navigationObserver(event);
});
}
private navigationObserver(event: Event): void {
if (event instanceof NavigationStart) {
// Increase 1% every 25 milliseconds, adjust it to your preference
this.progressTimer = setInterval(() => {
this.loading();
}, 25);
}
if (event instanceof NavigationEnd) {
// When the navigation finishes, fill the bar completely
this.progressValue = 100;
/*
* Uncomment this block to simulate a delay (for testing), because if you
* are in a local environment or the request is to a 'light' or very fast resource,
* the progress bar will appear at 100%.
*/
/*
setTimeout(() => {
this.progressValue = 100;
}, 2000);
*/
}
/*
* If the navigation is canceled or an error occurs,
* stop the progress bar and change its color.
*/
if (event instanceof NavigationCancel) {
this.stopProgress = true;
this.progressColor = 'accent';
}
if (event instanceof NavigationError) {
this.stopProgress = true;
this.progressColor = 'warn';
}
}
// Function to increase the value of the progress bar
private loading(): void {
/*
* Leave 5% in case an unusual delay occurs, in the previous
* function it is filled to 100% if the load ends successfully
*/
if (this.progressValue >= 95 || this.stopProgress) {
clearInterval(this.progressTimer);
} else {
this.progressValue++;
}
}
}
Template:
<mat-progress-bar [value]="progressValue" [color]="progressColor">
</mat-progress-bar>
<div *ngIf="progressValue == 100; else elseBlock">
<h1>Loaded!</h1>
</div>
<ng-template #elseBlock>
<h1>Loading...</h1>
</ng-template>
Upvotes: 1