来自 Angular 的 ExpressionChangedAfterItHasBeenCheckedError

pad*_*dhu 5 exception angular

这是我原来问题的延续

stackoverflow.com/questions/44596418/angular-throws-expressionchangedafterithasbeencheckederror-with-textarea

这仍然没有解决。我重新创建了原始的plunkr来模拟实际项目,发现它与textarea无关。

当我通过单击列表中的项目进入详细信息页面时,抛出异常ExpressionChangedAfterItHasBeenCheckedError。仅当src/detailitems.ts的 CodeView在数组中有多个元素时才会发生这种情况。CodeView 项以详细形式定义字段。

import { FormBase } from './formbase'
import { ItemBase, TextboxItemBase } from './itembase'

export class CodeView extends FormBase {

    static getItems() :ItemBase[] {

    let items: ItemBase[] = [

        new TextboxItemBase(
            {
                key: 'id',
                label: 'ID',
                value: '',
                required: true,
                enabled: false,
                readOnly: true,
                size: 36
            }
        )
,
        new TextboxItemBase(
            {
                key: 'description',
                label: 'Description',
                required: true,
                size: 20

            }
        )            
    ];

    return items;
}

}
Run Code Online (Sandbox Code Playgroud)

如果我修改代码使 CodeView 只有 1 个项目,那么异常就会消失。

异常Plunkr

没有例外 Plunkr(只有一项在 detailitems)

yur*_*zui 4

您的错误来自A-Item该节点的组件,更准确地说

<div [formGroup]="form"
Run Code Online (Sandbox Code Playgroud)

当你有这样的绑定时,Angular 将自动创建NgControlStatusGroup根据控件状态(有效/无效/脏/等)设置 CSS 类的指令。

export const ngControlStatusHost = {
  '[class.ng-untouched]': 'ngClassUntouched',
  '[class.ng-touched]': 'ngClassTouched',
  '[class.ng-pristine]': 'ngClassPristine',
  '[class.ng-dirty]': 'ngClassDirty',
  '[class.ng-valid]': 'ngClassValid', // you get error in this binding
  '[class.ng-invalid]': 'ngClassInvalid',
  '[class.ng-pending]': 'ngClassPending',
};
Run Code Online (Sandbox Code Playgroud)

第一次,您不会为您的控件提供任何价值。这就是为什么valid您的表单的属性是false. ngModel然后,您可以在更改检测周期中使用它来填充它,并且表单变得有效。的有效属性form是根据您的所有控件计算得出的。如果您只有一个控件,则有效属性将仅依赖于一个控件,并且A-Item组件不会引发错误。

我会在渲染之前准备数据。

可以打开form.component.ts,找到以下代码

this.formItems.forEach(item => {
   group[item.key] = item.BuildControl();
   this.items.push(new formObjectItem(item, this.getData(item.key)));
});
Run Code Online (Sandbox Code Playgroud)

那么你需要修补表单的数据

this.formItems.forEach(item => {
   group[item.key] = item.BuildControl();
   this.items.push(new formObjectItem(item, this.getData(item.key)));
   group[item.key].patchValue(this.getData(item.key)); // <== this line
});
Run Code Online (Sandbox Code Playgroud)

或者

this.formItems.forEach(item => {
   group[item.key] = item.BuildControl();
   const value = this.getData(item.key);
   this.items.push(new formObjectItem(item, value));
   group[item.key].patchValue(value);
});
Run Code Online (Sandbox Code Playgroud)

这样您的表单将与您的值同步并具有正确的状态。

在这种情况下,您还可以从组件中删除itemValue和 ,因为反应式模型将完成所有工作。ngModelA-Item

叉形插头

你不会收到这样的错误

还有一点提示:

import * as Rx from 'rxjs/Rx'
Run Code Online (Sandbox Code Playgroud)

您将把所有 rxjs 库发送到您的包中