在我的主组件中,我呈现了一个表单,它的表单组位于子组件中,主组件用一些默认值初始化,子组件用一些验证器和其他逻辑初始化。主组件用一些默认值初始化,子组件用一些验证器和其他逻辑初始化自己。
现在我在想,如果有一个 valueChanges
在主窗体上订阅,主组件会以某种方式自动获取子窗体组中的变化。但是缺少了一个连接部分,因为即使在子表单组中出现验证错误,表单也总是 "有效 "的。
我漏掉了什么?
main.component.ts:
ngOnInit() {
this.initializeFormGroup();
this.form.valueChanges.subscribe(
result => console.log(this.form.valid); // always outputs true!?
);
});
}
private initializeFormGroup(): void {
this.form = this.formBuilder.group({
child1: this.formBuilder.group({}),
child2: this.formBuilder.group({})
});
}
main.component.html:
<form [formGroup]="form">
<child1></child1>
<child2></child2>
</form>
child1.component.ts:
form: FormGroup;
ngOnInit(): void {
this.initializeFormGroup();
this.checkStuffAndAddValidators();
}
get formArray(): FormArray {
return this.form.get('array') as FormArray;
}
private initializeFormGroup(): void {
this.form = this.formBuilder.group({
array: this.formBuilder.array([])
});
}
private checkStuffAndAddValidators(): any {
const newGroup = this.formBuilder.group({
inputA: ['', [Validators.required]],
inputB: ['']
});
if (this.someConditionIsTrue) {
newGroup
.get('inputB')
.setValidators([MyValidator]);
newGroup.updateValueAndValidity();
}
this.array.push(newGroup);
});
}
child1.component.html:
<div [formGroup]="form">
<div formArrayName="array" *ngFor="let control of formArray.controls; let i = index">
<ng-container formGroupName="{{ i }}">
<input name="inputA" formControlName="inputA" />
<input name="inputB" formControlName="inputB" />
</ng-container>
</div>
child2.component.ts:
form: FormGroup;
ngOnInit(): void {
this.initializeFormGroup();
}
get formArray(): FormArray {
return this.form.get('array') as FormArray;
}
addInput() {
if (!this.formArray.valid) {
return;
}
this.formArray.push(this.createNewFormGroup());
}
removeInput(index: number) {
this.formArray.removeAt(index);
}
private initializeFormGroup(): void {
this.form = this.formBuilder.group({
array: this.formBuilder.array([this.createNewFormGroup()])
});
}
private createNewFromGroup(): FormGroup {
return this.formBuilder.group({
inputA: ['', [Validators.required]],
inputB: ['', [Validators.required]]
});
child2.component.html。
<div [formGroup]="form">
<div formArrayName="array" *ngFor="let control of formArray.controls; let i = index">
<ng-container formGroupName="{{ i }}">
<input name="inputA" formControlName="inputA" />
<a (click)="removeInput(i)">del</a>
<a (click)="addInput()">add</a>
<input name="inputB" formControlName="inputB" />
<a (click)="removeInput(i)">del</a>
<a (click)="addInput()">add</a>
</ng-container>
</div>
在你监听变化的主组件中,formBuilder没有任何验证。只有在子组件中它们才会被验证。如果你在子组件中监听变化,你可能会看到表单并不总是有效。你可以在子组件中监听变化,并使用一个 EventEmitter
或者你可以在main.component中为表单实例添加验证。
为了确保你能在main.component中调试并检查表单中是否有任何验证。
子组件有自己的表单,并且不链接到父表单,你需要将表单组传递给子组件。
<form [formGroup]="form">
<child1 [form]="form.get('child1')></child1>
<child2 [form]="form.get('child2')></child2>
</form>