在使用 时,Angular 6 报了 ExpressionChangedAfterItHasBeenCheckedError 错误。

19 浏览
0 Comments

在使用 时,Angular 6 报了 ExpressionChangedAfterItHasBeenCheckedError 错误。

我在Angular 6中遇到以下错误:

当我移除第二个`mat-tab`时,错误消失了。在其他类似的组件中,我没有将这两个表单放在`mat-tab-group`和`mat-tab`中,也没有这个错误。花了一段时间找出差异所在。

错误信息如下:

ExpressionChangedAfterItHasBeenCheckedError: 表达式在检查之后发生了变化。之前的值为'ng-valid: true',当前的值为'ng-valid: false'。

环境如下:

Angular CLI: 6.2.8

Node: 11.9.0

OS: linux x64

Angular:

ts文件(export class ElectricityRateListComponent extends SelectableEntitiesListComponent)如下:

public displayedColumnsArray = [
    'select',
    'id',
    'energyRate',
    'mainTransmissionRate',
    'publicServiceRate',
    'validityStartDate',
    'validityEndDate',
    'electricityType',
    'city',
];
public statusMessage: string = ''
public selectedTabIndex: number = 0
protected _elTypeAddSelect: DBEntitySelect //ElectricityType: Enumerate
protected _elTypeEditSelect: DBEntitySelect //ElectricityType: Enumerate
protected _cityAddSelect: DBEntitySelect //City: Enumerate
protected _cityEditSelect: DBEntitySelect //City: Enumerate
constructor(
    protected router: Router,
    public messageService: MessageService,
    protected logger: LoggerService,
    protected route: ActivatedRoute,
    protected entitiesService: ElectricityRateService,
    protected enumeratesService: EnumerateService,
    protected formBuilder: FormBuilder,
    public formService: DynamicFormService,
    iconRegistry: MatIconRegistry,
    sanitizer: DomSanitizer,
    // private location: Location
) {
    super(router, messageService, logger, route, entitiesService, formBuilder, formService, iconRegistry, sanitizer, new ElectricityRate());
    (...)
}
/**
* Common to add and edit forms
*
* @param aStrangeObject
*/
protected _getCommonFormControlModel(aStrangeObject: Enumerate): DynamicFormControlModel[] {
    let lEntity: ElectricityRate = new ElectricityRate().deserialize(
        aStrangeObject
    )
    console.debug(
        "-----getAddFormControlModel->",
        aStrangeObject,
        lEntity.validityStartDate.constructor.name,
        lEntity.validityEndDate.constructor.name
    )
    const result: DynamicFormControlModel[] = [
        new DynamicInputModel({
            id: "energyRate",
            label: "Energy Rate",
            value: lEntity.energyRate,
            inputType: DYNAMIC_FORM_CONTROL_INPUT_TYPE_NUMBER,
            min: ElectricityRate.MIN_ELECTRICITY_RATE,
            max: ElectricityRate.MAX_ELECTRICITY_RATE,
            placeholder: "Energy Rate"
        }),
        new DynamicInputModel({
            id: "mainTransmissionRate",
            label: "Transmission Rate",
            inputType: DYNAMIC_FORM_CONTROL_INPUT_TYPE_NUMBER,
            min: ElectricityRate.MIN_ELECTRICITY_RATE,
            max: ElectricityRate.MAX_ELECTRICITY_RATE,
            value: lEntity.mainTransmissionRate.toString(),
            placeholder: "Transmission Rate"
        }),
        new DynamicInputModel({
            id: "publicServiceRate",
            label: "Public Service Rate",
            inputType: DYNAMIC_FORM_CONTROL_INPUT_TYPE_NUMBER,
            min: ElectricityRate.MIN_ELECTRICITY_RATE,
            max: ElectricityRate.MAX_ELECTRICITY_RATE,
            value: lEntity.publicServiceRate.toString(),
            placeholder: "Public Service Rate"
        }),
        new DynamicInputModel({
            id: "validityStartDate",
            label: "Validity start date",
            inputType: DYNAMIC_FORM_CONTROL_INPUT_TYPE_DATE,
            maxLength: 10,
            value: MiscHelper.dateToDynamicInputDate(lEntity.validityStartDate),
            placeholder: "Validity start date"
        }),
        new DynamicInputModel({
            id: "validityEndDate",
            label: "Validity end date",
            inputType: DYNAMIC_FORM_CONTROL_INPUT_TYPE_DATE,
            value: MiscHelper.dateToDynamicInputDate(lEntity.validityEndDate),
            placeholder: "Validity end date"
        })
    ]
    return result
}
/**
* called by SelectableEntitiesListComponent->onInit
*
* @param aStrangeObject
*/
protected _getAddFormControlModel(aStrangeObject: Enumerate): DynamicFormControlModel[] {
    //console.debug('getAddFormControlModel->aStrangeObject:', aStrangeObject)
    let lEntity: Enumerate = new Enumerate().deserialize(aStrangeObject)
    console.debug('-----getAddFormControlModel->aStrangeObject, lEntity:', aStrangeObject, lEntity)
    //Add form fields
    const result: DynamicFormControlModel[] = this._getCommonFormControlModel(aStrangeObject)
    result.push(this._elTypeAddSelect.asDynamicInputModel())
    result.push(this._cityAddSelect.asDynamicInputModel())
    return result
}
/**
* Built onRowClicked
*
* @param anId
* @param aStrangeObject can be a row of dataTable
*/
protected _getEditFormControlModel(aStrangeObject: Enumerate): DynamicFormControlModel[] {
    console.log('getEditFormControlModel:', aStrangeObject)
    let result = this._getCommonFormControlModel(aStrangeObject)
    result = result.concat(DBEntity.getIdFormControlModel('id', aStrangeObject))
    result.push(this._elTypeEditSelect.asDynamicInputModel())
    result.push(this._cityEditSelect.asDynamicInputModel())
    // console.log('getEditFormControlModel:', result)
    return result
}

这篇文章高度相关。

0
0 Comments

Angular 6中使用出现(ExpressionChangedAfterItHasBeenCheckedError)的原因及解决方法

在使用时,如果遇到ExpressionChangedAfterItHasBeenCheckedError错误,通常与开发阶段的生命周期钩子(如ngAfterViewInit)有关。这个错误通常在开发的后期阶段出现,当我们在模板中使用更多的表达式,并且通常开始使用一些生命周期钩子(如AfterViewInit)。

解决这个问题的一个可能的方法是,在ngAfterViewInit()中对数据源进行排序之前,使用setTimeout或delay(0)延迟一段时间。这样做的原因是,让Angular首先显示loading flag为false的数据。

这种解决方法的原理是:

1. loading指示器的初始值为false,因此初始时不会显示loading指示器。

2. ngAfterViewInit()被调用,但是数据源不会立即被调用,所以不会通过ngAfterViewInit()同步地进行加载指示器的修改。

3. Angular完成视图渲染,并在屏幕上反映最新的数据变化,JavaScript VM转换完成。

4. 一段时间后,setTimeout()调用(也可以在delay(0)内部使用),然后数据源加载其数据。

5. loading flag设置为true,现在显示loading指示器。

6. Angular完成视图渲染,并在屏幕上反映最新的变化,这导致loading指示器显示出来。

除了使用setTimeout,还可以使用changeDetector.detectChanges()作为另一种可能的解决方法。changeDector是一个注入的ChangeDetectorRef,这是解决这个问题的另一种广泛使用的方法。

您还可以使用Promise.resolve作为setTimeout的替代方法。

以上解决方法的具体情况可以在Angular官方文档以及stackoverflow上的相关回答中找到更详细的解释和示例。

希望这些信息对您有所帮助!

0