I am wondering why my loading spinner is not firing, and I think it may be due to my confusion in regard to my LoadingService at the app level, and my LoadingService as a provider at the page level.
APP LEVEL
app.component.html
<app-header></app-header>
<messages></messages>
<loading></loading>
<router-outlet></router-outlet>
app.module.ts
@NgModule({
declarations: [
...
LoadingComponent,
...
]
app.component.ts
providers: [LoadingService]
LOADING COMPONENT AND SERVICE
loading.component.html
<div class="spinner-container" *ngIf="loadingService.loading$ | async">
<mat-spinner></mat-spinner>
</div>
loading.service.ts
import { Injectable } from "@angular/core";
import { BehaviorSubject, Observable, of } from "rxjs";
@Injectable()
export class LoadingService {
private loadingSubject = new BehaviorSubject<boolean>(false);
loading$: Observable<boolean> = this.loadingSubject.asObservable();
loadingOn() {
this.loadingSubject.next(true);
}
loadingOff() {
this.loadingSubject.next(false);
}
}
PAGE THAT USES THE LOADER
page.component.ts
@Component({
...
providers: [LoadingService]
})
constructor(private loadingService: LoadingService) { }
ngOnInit() {
...
this.reloadParameters();
...
}
reloadParameters() {
this.loadingService.loadingOn();
this.parameters$ = this.adminService.getParameters().pipe(
catchError(err => {
const message = "Could Not Load Parameters";
this.messagesService.showErrors(message);
console.log(message, err);
return throwError(err);
}),
finalize(() => this.loadingService.loadingOff())
);
}
A console.log tells me it hits the loadingOn() method and the loading$ observable is true. But no spinner, even when I comment out the api call which should just trigger the spinner indefinitely. But instead, it doesn't trigger the spinner at all.
Short Answer:
Based on how you have your components set up, it seems like you should just use
providedIn: rootin your service instead of addingLoadingServiceto theprovidersarray of several different components.From the angular docs:
Long answer: Learn about Dependency Injection and Hierarchical Injectors
There is an even more interesting answer as to why you are seeing this issue:
This issue is caused by the way you are providing the service in several different components.
From the docs:
In other words, the instance of LoadingService that PageComponent is using is not the same instance that LoadComponent is using. If you want a global shared instance of the service (which I think is the most common use case for Angular Services),
providedIn: rootin the service itself (see short answer) is all you'll need to do.DI is one of the more complicated topics to learn about regarding Angular. There is official documentation covering it, but I would highly recommend this video explanation / playlist on YouTube.