Le routeur Angular actuel fournit des événements de navigation. Vous pouvez vous abonner à ces événements et modifier l'interface utilisateur en conséquence. N'oubliez pas de tenir compte d'autres événements tels que NavigationCancel
et NavigationError
pour arrêter la toupie en cas d'échec des transitions de routeur.
app.component.ts - votre composant racine
...
import {
Router,
// import as RouterEvent to avoid confusion with the DOM Event
Event as RouterEvent,
NavigationStart,
NavigationEnd,
NavigationCancel,
NavigationError
} from '@angular/router'
@Component({})
export class AppComponent {
// 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 {
if (event instanceof NavigationStart) {
this.loading = true
}
if (event instanceof NavigationEnd) {
this.loading = false
}
// Set loading state to false in both of the below events to hide the spinner in case a request fails
if (event instanceof NavigationCancel) {
this.loading = false
}
if (event instanceof NavigationError) {
this.loading = false
}
}
}
app.component.html - votre vue Racine
<div class="loading-overlay" *ngIf="loading">
<!-- show something fancy here, here with Angular 2 Material's loading bar or circle -->
<md-progress-bar mode="indeterminate"></md-progress-bar>
</div>
Amélioration des performances Réponse : Si vous vous souciez des performances, il existe une meilleure méthode, elle est légèrement plus fastidieuse à mettre en œuvre mais l'amélioration des performances vaudra le travail supplémentaire. Au lieu d'utiliser *ngIf
pour afficher conditionnellement le compteur rotatif, nous pourrions tirer parti de l'outil Angular NgZone
et Renderer
pour activer/désactiver le spinner, ce qui permet de contourner la détection de changement d'Angular lorsque nous changeons l'état du spinner. J'ai trouvé que cela rendait l'animation plus fluide par rapport à l'utilisation de la fonction *ngIf
ou un async
tuyau.
C'est similaire à ma réponse précédente avec quelques modifications :
app.component.ts - votre composant racine
...
import {
Router,
// import as RouterEvent to avoid confusion with the DOM Event
Event as RouterEvent,
NavigationStart,
NavigationEnd,
NavigationCancel,
NavigationError
} from '@angular/router'
import {NgZone, Renderer, ElementRef, ViewChild} from '@angular/core'
@Component({})
export class AppComponent {
// Instead of holding a boolean value for whether the spinner
// should show or not, we store a reference to the spinner element,
// see template snippet below this script
@ViewChild('spinnerElement')
spinnerElement: ElementRef
constructor(private router: Router,
private ngZone: NgZone,
private renderer: Renderer) {
router.events.subscribe((event: RouterEvent) => {
this._navigationInterceptor(event)
})
}
// Shows and hides the loading spinner during RouterEvent changes
private _navigationInterceptor(event: RouterEvent): void {
if (event instanceof NavigationStart) {
// We wanna run this function outside of Angular's zone to
// bypass change detection
this.ngZone.runOutsideAngular(() => {
// For simplicity we are going to turn opacity on / off
// you could add/remove a class for more advanced styling
// and enter/leave animation of the spinner
this.renderer.setElementStyle(
this.spinnerElement.nativeElement,
'opacity',
'1'
)
})
}
if (event instanceof NavigationEnd) {
this._hideSpinner()
}
// Set loading state to false in both of the below events to
// hide the spinner in case a request fails
if (event instanceof NavigationCancel) {
this._hideSpinner()
}
if (event instanceof NavigationError) {
this._hideSpinner()
}
}
private _hideSpinner(): void {
// We wanna run this function outside of Angular's zone to
// bypass change detection,
this.ngZone.runOutsideAngular(() => {
// For simplicity we are going to turn opacity on / off
// you could add/remove a class for more advanced styling
// and enter/leave animation of the spinner
this.renderer.setElementStyle(
this.spinnerElement.nativeElement,
'opacity',
'0'
)
})
}
}
app.component.html - votre vue Racine
<div class="loading-overlay" #spinnerElement style="opacity: 0;">
<!-- md-spinner is short for <md-progress-circle mode="indeterminate"></md-progress-circle> -->
<md-spinner></md-spinner>
</div>
0 votes
stackoverflow.com/questions/21512893/
5 votes
La question liée ci-dessus (le commentaire d'AndrewL64) concerne AngularJS, et non "Angular" (2+).