首页 > 解决方案 > Angular 的 ngIF 显示加载器无法正常工作

问题描述

我对一个问题感到非常困惑。当我的应用程序从异步函数获取答案时,我需要显示加载器微调器。为了解决这个任务,我从我的app.component粘贴加载器组件,如下所示:

<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>

如果 isShowIndicator (boolean) 为真 - 加载器正确显示,如果它为假 - 加载器消失。

但是我需要更改这个变量的值,所以我尝试在我的 app.component.ts 文件中进行 3 次尝试,所有这些尝试都是更改 isShowIndicator 的值,但是我的加载器没有出现。你能解释一下,为什么会这样?谢谢你。

app.component.ts 的代码是:

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();

  }
}

加载器服务是这样实现的:

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);
    }
}

在我的代码中,我给加载器服务赋予了新的价值,如下所示:

 constructor(private loader: LoaderService) {
    this.loader.display(true);
    //some async code
    this.loader.display(false); // inside the subscribe method of course
  }

标签: angular

解决方案


如果你通过 HttpInterceptors 解决这个问题可能会更好。

像这样的东西:

@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();
  }
}

参考

编辑

在您的代码中

 constructor(private loader: LoaderService) {
    this.loader.display(true);
    //some async code
    this.loader.display(false); // inside the subscribe method of course
  }

你需要做的是

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)
    );
}

推荐阅读