Eri*_*and 15 javascript forms angular
我的反应形式是深层的三个组成部分.父组件创建一个没有任何字段的新表单,并将其传递给子组件.
首先,外形有效.稍后,子组件会添加带有验证器的新表单元素(失败),使外部表单无效.
我在控制台中收到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({});
}
}
Run Code Online (Sandbox Code Playgroud)
子组件
@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);
}
Run Code Online (Sandbox Code Playgroud)
儿童组件
@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);
}
}
Run Code Online (Sandbox Code Playgroud)
Max*_*kyi 21
要了解问题,您需要阅读有关ExpressionChangedAfterItHasBeenCheckedError错误文章的所有内容.
对于您的特定情况,问题是您正在创建表单AppComponent并{{myForm.valid}}在DOM中使用插值.这意味着角将运行创建和运行updateRenderer功能的AppComponent的更新DOM.然后使用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); <--------
Run Code Online (Sandbox Code Playgroud)
控件变为无效,因为您没有提供初始值并且您指定了所需的验证器.因此整个表单变得无效,表达式的{{myForm.valid}}计算结果为false.但是当Angular运行变更检测时,AppComponent它被评估为true.这就是错误所说的.
一个可能的解决方法是在开始时将表单标记为无效,因为您计划添加所需的验证器,但似乎Angular不提供此类方法.您最好的选择可能是异步添加控件.事实上,这就是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});
});
}
Run Code Online (Sandbox Code Playgroud)
所以对你来说这将是:
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); <-------
})
}
}
Run Code Online (Sandbox Code Playgroud)
或者在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;
})
}
}
Run Code Online (Sandbox Code Playgroud)