Reputation: 71
I'm very confused about one problem. I need to display the loader spinner while my app is getting answers from an async function. To solve this task I paste the loader component from my app.component like this:
<div class="sticky-top">
<app-menu></app-menu>
</div>
<div>
<router-outlet></router-outlet>
</div>
<!-- Loader-->
<div *ngIf=" isShowIndicator" class="position">
<app-loader > </app-loader>
</div>
if the isShowIndicator (boolean) is true - the loader is displayed correctly if it false - the loader is disappeared.
But I need to change the value of this variable, so I try to do three attempts in my app.component.ts file, and all of this attempts is change the value of isShowIndicator, but my loader didn't appear. Can you explain me, why this is happened? Thank you.
The code of app.component.ts is :
import { Component, ChangeDetectorRef } from '@angular/core';
import { LoaderService } from './services/additional/loader';
import { Router, RouterModule, NavigationStart, NavigationEnd, RouterEvent, Event } from '@angular/router';
import { Observable } from 'rxjs';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
isShowIndicator: boolean = true;
constructor(private _router: Router, private loader: LoaderService, public cd: ChangeDetectorRef) {
// first attempt - use the Observable from my loader service:
this.GetLoadingState().subscribe(element => {
console.log("Show Indicator Obsrvable " + `${element}`);
this.isShowIndicator = element;
console.log("Show Indicator Obsrvable " + this.isShowIndicator);
})
// second attempt - use router events to change the value of isShowIndicator
this._router.events.subscribe((routerEvent: Event) => {
if (routerEvent instanceof NavigationStart) {
this.isShowIndicator = true;
console.log("true from route " + this.isShowIndicator);
}
else if (routerEvent instanceof NavigationEnd) {
console.log("false from route " + this.isShowIndicator);
this.isShowIndicator = false;
}
});
// third attempt is use the behavior subject object
this.loader.ShowIndicator.subscribe(element => {
console.log("Show Indicator " + `${element}`);
this.isShowIndicator = element;
console.log("Show Indicator " + this.isShowIndicator);
});
}
GetLoadingState(): Observable<boolean> {
return this.loader.ShowIndicator.asObservable();
}
}
The loader service is implement like this:
import { Injectable } from '@angular/core';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
@Injectable({
providedIn: 'root'
})
export class LoaderService {
public ShowIndicator: BehaviorSubject<boolean> =
new BehaviorSubject<boolean>(true);
display (value: boolean) {
this.ShowIndicator.next(value);
}
}
in my code I gave the new value to loader service like this:
constructor(private loader: LoaderService) {
this.loader.display(true);
//some async code
this.loader.display(false); // inside the subscribe method of course
}
Upvotes: 1
Views: 829
Reputation: 30565
It may be better If you solve this by HttpInterceptors.
Something like this:
@Injectable({
providedIn: 'root'
})
export class LoaderInterceptorService implements HttpInterceptor {
constructor(private loaderService: LoaderService) { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
this.showLoader();
return next.handle(req).pipe(tap((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
this.onEnd();
}
},
(err: any) => {
this.onEnd();
}));
}
private onEnd(): void {
this.hideLoader();
}
private showLoader(): void {
this.loaderService.show();
}
private hideLoader(): void {
this.loaderService.hide();
}
}
Edit
In your code
constructor(private loader: LoaderService) {
this.loader.display(true);
//some async code
this.loader.display(false); // inside the subscribe method of course
}
what you need to do is
constructor(private loader: LoaderService) {
this.loader.display(true);
this.subscription = this.dataSvc.data.subscribe(
data => console.log('Data:', data),
err => console.log(err),
() => this.loader.display(false)
);
}
Upvotes: 1