Angular 11 - 验证在 for 循环中生成的子表单
Angular 11 - Validating a child form generated in a for loop
我正在使用 Angular 响应式表单。我的父组件有一个表单,一个 Add Form
。 Submit
和 Reset
按钮。当我单击 Add form
时,它会向 DOM 添加一个名为 profile-form
的子表单。 profile-form
有两个字段 First Name
和 Email
。这个想法是重复使用 profile-form
组件任意次数,点击添加按钮。每个表单都需要验证,父表单应该知道每个子表单的验证状态。
我的父表单使用此 HTML 在 for 循环中生成子表单。
<div *ngFor="let fg of formList.controls; let infoIndex = index">
<app-profile-form formControlName="fg" [formList]="formList"
[formIndex]="infoIndex"></app-profile-form>
</div>
当我查看控制台时,我似乎收到一条错误消息,指出在 formList.controls
中找不到 formControlName 'fg'
。如何修复我的父表单和子表单之间的 formControls 映射,以便验证有效?
让我们尝试分析表格。
您希望下面是表格的最终值
{
"formList": [
{
"firstName": "",
"email": ""
},
{
"firstName": "",
"email": ""
},
{
"firstName": "",
"email": ""
}
]
}
在上面我们有
form => FormGroup : form
formList => FormArray : formList
1 => FormControl with value {email: '', firstName} : 1
2 => FormControl with value {email: '', firstName} : 2
3 => FormControl with value {email: '', firstName} : 3
所以在表单中我们必须有这个结构才能工作
<form [formGroup]="signupForm" (ngSubmit)="submit()">
<ng-container formArrayName='formList'>
<div *ngFor="let fg of formList.controls; let infoIndex = index">
<app-profile-form [formControlName]="infoIndex" [formIndex]="infoIndex"></app-profile-form>
</div>
</ng-container>
<button>Sign Up</button>
<button type="button" (click)="resetForm()">Reset</button>
</form>
其他一些修订将包括
改变formListGroupDef
return this.formBuilder.control(
{
firstName: "",
email: ""
},
Validators.required
);
注册表格
this.signupForm = this.formBuilder.group({
formList: this.formBuilder.array([
this.formListGroupDef()
])
});
我也对你的ProfileFormComponent
做了一些修改
export class ProfileFormComponent implements ControlValueAccessor, OnDestroy {
@Input() formIndex: any;
destroyed$ = new Subject<any>();
form: FormGroup;
get firstNameControl() {
return this.form.controls.firstName;
}
get emailControl() {
return this.form.controls.email;
}
constructor(private formBuilder: FormBuilder) {
this.form = this.formBuilder.group({
firstName: ["", Validators.required],
email: ["", Validators.required]
});
this.form.valueChanges.pipe(
filter(({firstName, email}) => firstName.length > 0 || email.length > 0 ),
takeUntil(this.destroyed$)
).subscribe(value => {
this.onChange(value);
this.onTouched();
});
}
ngOnDestroy() {
this.destroyed$.next();
}
onChange: any = () => {};
onTouched: any = () => {};
registerOnChange(fn) {
this.onChange = fn;
}
writeValue(value) {
if (value) {
this.form.patchValue(value);
}
}
registerOnTouched(fn) {
this.onTouched = fn;
}
validate(_: FormControl) {
return this.form.valid ? null : { profile: { valid: false } };
}
我正在使用 Angular 响应式表单。我的父组件有一个表单,一个 Add Form
。 Submit
和 Reset
按钮。当我单击 Add form
时,它会向 DOM 添加一个名为 profile-form
的子表单。 profile-form
有两个字段 First Name
和 Email
。这个想法是重复使用 profile-form
组件任意次数,点击添加按钮。每个表单都需要验证,父表单应该知道每个子表单的验证状态。
我的父表单使用此 HTML 在 for 循环中生成子表单。
<div *ngFor="let fg of formList.controls; let infoIndex = index">
<app-profile-form formControlName="fg" [formList]="formList"
[formIndex]="infoIndex"></app-profile-form>
</div>
当我查看控制台时,我似乎收到一条错误消息,指出在 formList.controls
中找不到 formControlName 'fg'
。如何修复我的父表单和子表单之间的 formControls 映射,以便验证有效?
让我们尝试分析表格。
您希望下面是表格的最终值
{
"formList": [
{
"firstName": "",
"email": ""
},
{
"firstName": "",
"email": ""
},
{
"firstName": "",
"email": ""
}
]
}
在上面我们有
form => FormGroup : form
formList => FormArray : formList
1 => FormControl with value {email: '', firstName} : 1
2 => FormControl with value {email: '', firstName} : 2
3 => FormControl with value {email: '', firstName} : 3
所以在表单中我们必须有这个结构才能工作
<form [formGroup]="signupForm" (ngSubmit)="submit()">
<ng-container formArrayName='formList'>
<div *ngFor="let fg of formList.controls; let infoIndex = index">
<app-profile-form [formControlName]="infoIndex" [formIndex]="infoIndex"></app-profile-form>
</div>
</ng-container>
<button>Sign Up</button>
<button type="button" (click)="resetForm()">Reset</button>
</form>
其他一些修订将包括
改变formListGroupDef
return this.formBuilder.control(
{
firstName: "",
email: ""
},
Validators.required
);
注册表格
this.signupForm = this.formBuilder.group({
formList: this.formBuilder.array([
this.formListGroupDef()
])
});
我也对你的ProfileFormComponent
export class ProfileFormComponent implements ControlValueAccessor, OnDestroy {
@Input() formIndex: any;
destroyed$ = new Subject<any>();
form: FormGroup;
get firstNameControl() {
return this.form.controls.firstName;
}
get emailControl() {
return this.form.controls.email;
}
constructor(private formBuilder: FormBuilder) {
this.form = this.formBuilder.group({
firstName: ["", Validators.required],
email: ["", Validators.required]
});
this.form.valueChanges.pipe(
filter(({firstName, email}) => firstName.length > 0 || email.length > 0 ),
takeUntil(this.destroyed$)
).subscribe(value => {
this.onChange(value);
this.onTouched();
});
}
ngOnDestroy() {
this.destroyed$.next();
}
onChange: any = () => {};
onTouched: any = () => {};
registerOnChange(fn) {
this.onChange = fn;
}
writeValue(value) {
if (value) {
this.form.patchValue(value);
}
}
registerOnTouched(fn) {
this.onTouched = fn;
}
validate(_: FormControl) {
return this.form.valid ? null : { profile: { valid: false } };
}