来自Angular的ExpressionChangedAfterItHasBeenCheckedError

时间:2017-07-10 21:04:23

标签: angular exception

这是我原始问题的延续

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

尚未解决。我重新创建了orignal 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;
}

}

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

Exception Plunkr

No Exception Plunkr(在详细资料中只有一项)

1 个答案:

答案 0 :(得分:3)

您的错误来自A-Item组件,更精确地来自此节点

<div [formGroup]="form"

当你有这样的绑定时,会自动创建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',
};

您第一次没有为控件提供任何价值。这就是为什么您的表单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)));
});

然后你需要修补表格

的数据
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
});

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

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

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

<强> Forked Plunker

你没有得到这样的错误

还有一个提示:

import * as Rx from 'rxjs/Rx'

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