动态嵌套反应形式:ExpressionChangedAfterItHasBeenCheckedError
我的反应形式是三个组件级别深。父组件创建一个没有任何字段的新表单,并将其传递给子组件。动态嵌套反应形式:ExpressionChangedAfterItHasBeenCheckedError
首先,外形是有效的。稍后,子组件添加带有验证器的新表单元素(失败),从而使外部表单无效。
我收到的控制台ExpressionChangedAfterItHasBeenCheckedError错误。我想修复这个错误。
不知何故,这只发生在我添加第三层嵌套。同样的方法似乎适用于两层嵌套。
Plunker:https://plnkr.co/edit/GymI5CqSACFEvhhz55l1?p=preview
父组件
@Component({
selector: 'app-root',
template: `
myForm.valid: <b>{{myForm.valid}}</b>
<form>
<app-subform [myForm]="myForm"></app-subform>
</form>
`
})
export class AppComponent implements OnInit {
...
ngOnInit() {
this.myForm = this.formBuilder.group({});
}
}
子组件
@Component({
selector: 'app-subform',
template: `
<app-address-form *ngFor="let addressData of addressesData;"
[addressesForm]="addressesForm">
</app-address-form>
`
})
export class SubformComponent implements OnInit {
...
addressesData = [...];
constructor() { }
ngOnInit() {
this.addressesForm = new FormArray([]);
this.myForm.addControl('addresses', this.addressesForm);
}
子组件
@Component({
selector: 'app-address-form',
template: `
<input [formControl]="addressForm.controls.addressLine1">
<input [formControl]="addressForm.controls.city">
`
})
export class AddressFormComponent implements OnInit {
...
ngOnInit() {
this.addressForm = this.formBuilder.group({
addressLine1: [
this.addressData.addressLine1,
[ Validators.required ]
],
city: [
this.addressData.city
]
});
this.addressesForm.push(this.addressForm);
}
}
要了解你需要阅读Everything you need to know about the ExpressionChangedAfterItHasBeenCheckedError
error文章的问题。
对于您的特定情况,问题在于您要在AppComponent
中创建表单并在DOM中使用插值。这意味着更新DOM的的角度will run create and run updateRenderer function。然后,可以使用子的ngOnInit
生命周期挂钩与控件添加分组这种形式:因为你不提供初始值,指定所需的验证
export class AddressFormComponent implements OnInit {
@Input() addressesForm;
@Input() addressData;
ngOnInit() {
this.addressForm = this.formBuilder.group({
addressLine1: [
this.addressData.addressLine1,
[ Validators.required ] <-----------
]
this.addressesForm.push(this.addressForm); <--------
控制变为无效。因此整个表格变得无效,表达式{{myForm.valid}}
评估为false
。但是当Angular运行AppComponent
的变化检测时,它评估为true
。这就是错误所说的。
由于您打算添加必需的验证器,因此一种可能的解决方法是将表单标记为无效,但似乎Angular不提供此类方法。您的最佳选择可能是异步添加控件。事实上,这就是角做自己在来源:
const resolvedPromise = Promise.resolve(null);
export class NgForm extends ControlContainer implements Form {
...
addControl(dir: NgModel): void {
// adds controls asynchronously using Promise
resolvedPromise.then(() => {
const container = this._findContainer(dir.path);
dir._control = <FormControl>container.registerControl(dir.name, dir.control);
setUpControl(dir.control, dir);
dir.control.updateValueAndValidity({emitEvent: false});
});
}
所以你区分这将是:
const resolvedPromise = Promise.resolve(null);
@Component({
...
export class AddressFormComponent implements OnInit {
@Input() addressesForm;
@Input() addressData;
addressForm;
ngOnInit() {
this.addressForm = this.formBuilder.group({
addressLine1: [
this.addressData.addressLine1,
[ Validators.required ]
],
city: [
this.addressData.city
]
});
resolvedPromise.then(() => {
this.addressesForm.push(this.addressForm); <-------
})
}
}
或者使用一些变量在AppComponent
持有形式的国家,并用它在模板:
{{formIsValid}}
export class AppComponent implements OnInit {
myForm: FormGroup;
formIsValid = false;
constructor(private formBuilder: FormBuilder) {}
ngOnInit() {
this.myForm = this.formBuilder.group({});
this.myForm.statusChanges((status)=>{
formIsValid = status;
})
}
}
感谢您的非常详细的答案!欣赏它。 –
@ErikNijland,不客气)祝你好运 –
对于档案:第一种方法完美无缺地工作。第二个没有工作。它只是将相同的错误移动到另一个变量。还需要一个.subscribe来检查statusChanges。 –
检查[你需要了解的'ExpressionChangedAfterItHasBeenCheckedError'错误的一切(https://blog.angularindepth.com/everything-you-need-to-know-about-the-expressionchangedafterithasb eencheckederror-error-e3fd9ce7dbb4)文章 –
我在过去24小时内访问了该页面5次;)。仍然不知道如何解决它。 –
你参考 –