以角度

时间:2017-09-05 16:51:07

标签: angular angular2-template angular2-services angular2-components

我有很多需要从Web服务加载数据的组件。在加载过程中,我想显示一个覆盖整个站点的全局加载指示器。多个组件可能同时加载数据。

服务和服务订户

为了同步一个常见的加载指示器我编写了一个服务:

import { Observable } from "rxjs/Observable";
import { Observer } from "rxjs/Observer";
import { Injectable } from "@angular/core";
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

@Injectable()
export class GlobalLoadingIndicatorService {

    private _isLoadingSource = new BehaviorSubject<boolean>(false);
    public isLoadingObservable = this._isLoadingSource.asObservable();

    public get isLoading(): boolean{
        return this._loadingProcessCount > 0;
    }

    private _loadingProcessCount: number = 0;

    public addLoadingProcess(): void{
        this._loadingProcessCount += 1;
        this._isLoadingSource.next(this.isLoading);
    }

    public removeLoadingProcess(): void{
        this._loadingProcessCount -= 1;
        if(this._loadingProcessCount < 0){
            throw "Negative _loadingProcessCount is not possible.";
        }
        this._isLoadingSource.next(this.isLoading);
    }
}

在我的AppComponent(它是我的应用的根目录)中,我将Observable<boolean>存储在了一个属性isLoadingObservable中:

import { Component, OnDestroy, OnInit } from "@angular/core";
import { GlobalLoadingIndicatorService } from "../Services/GlobalLoadingIndicatorService.js";
import { Subscription } from "rxjs/Subscription";
import { Observable } from "rxjs";

@Component({
    selector: "app",
    templateUrl: "/Templates/App"
})
export class AppComponent implements OnInit{
    constructor(
        private _globalLoadingIndicatorService: GlobalLoadingIndicatorService
    ) { }

    public isLoadingObservable: Observable<boolean>;

    ngOnInit() {
        this.isLoadingObservable = this._globalLoadingIndicatorService.isLoadingObservable;
    }
}

在我的HTML模板中,我绑定isLoadingObservable

<div *ngIf="isLoadingObservable | async">Loading...</div>

添加/删除加载进程

现在,当我需要一个全局加载指示符时,我会注入服务并使用方法:

export class MyComponent implements OnInit, OnDestroy {
    constructor(
        private _myService: MyService,
        private _globalLoadingIndicatorService: GlobalLoadingIndicatorService
    ) { }

    ngOnInit(): void {        
        this._globalLoadingIndicatorService.addLoadingProcess();
        this._myService.getData().subscribe(
            x => {
                this.userGroups = x;
                this.userGroup = x.length > 0 ? x[0].id : null;
                this._globalLoadingIndicatorService.removeLoadingProcess();
            },
            error => {
                alert(error);
            }
        );
    }

问题

在某些(并非所有)组件中,我收到运行时错误:

  

ExpressionChangedAfterItHasBeenCheckedError:表达式在检查后发生了变化。之前的值:'[object Object]'。当前值:'true'

我读到了这个错误,发现我在Angular-Hook生命周期中更改了一个以UI Update结尾的变量。

其中我找到了这篇文章:Everything you need to know about the ExpressionChangedAfterItHasBeenCheckedError error
由于这篇文章,我不喜欢使用ChangeDetectorRef.detectChangessetTimeout的解决方案。

如何更改全球 -Loading-Indicator来解决此问题?

更多信息

我还在GitHub上找到了一个问题主题:ExpressionChangedAfterItHasBeenCheckedError when changing a component value in afterViewInit #14748
特别是8月4日 minuz 的解决方案:我看不出与我的代码有什么不同。为什么它适合他而不适合我?

0 个答案:

没有答案