如何解决将包含多个表单组的表单数组动态绑定到 Angular 12 响应式表单中的模板时出错
我的数据包含从 API 返回的人员对象数组,我必须为其动态生成控件并在 Angular 12 应用程序中显示。返回的数据如下所示。
{
"type": "Person","fields": [
{
"name": "fullName","label": "Full name","validation": {
"rules": {
"required": true,"maxLength": 100
},"errorMessages": {
"required": "Enter your full name","maxLength": "The full name must not exceed 100 characters"
}
}
},{
"name": "phoneNumber","label": "Phone number","maxLength": 16
},"errorMessages": {
"required": "Enter a valid phone number","maxLength": "The phone number must not exceed 16 characters"
}
}
},{
"name": "email","label": "Email","format": "^(([^<>()\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$"
},"errorMessages": {
"required": "Enter a valid email address","format": "The email address must be valid"
}
}
}
],"values": [
{
"id": 1,"fullName": null,"phoneNumber": null,"email": null
},{
"id": 2,"fullName": "ytrytrytr",{
"id": 3,"fullName": "test","phoneNumber": "2353535","email": "dfdw@ww.com"
}
]
}
我的 component.ts 文件中用于获取数据并创建表单数组以及该表单数组中的表单组的代码如下所示。
form!: FormArray;
personFields!: any;
personValues: any;
ngOnInit() {
this.personService.getData()
.subscribe((res: FormObject) => {
this.personFields = res.fields;
this.personValues = res.values;
this.form = new FormArray(this.personValues.map((value:
any)=>this.createPersonData(value)));
});
}
createPersonData(person: any) {
let personFormGroup = new FormGroup({});
let validationsArray = [];
this.personFields.forEach(formField => {
validationsArray = [];
if(formField.validation.rules.required) {
validationsArray.push(Validators.required);
}
if(formField.validation.rules.maxLength) {
validationsArray.push(Validators.maxLength(formField.validation.rules.maxLength));
}
if(formField.validation.rules.format) {
validationsArray.push(Validators.pattern(formField.validation.rules.format));
}
let formFieldValue = person[formField.name] ? person[formField.name] : null;
personFormGroup.addControl(formField.name,new FormControl(formFieldValue,validationsArray));
});
return personFormGroup;
}
现在,我绑定到模板 html 文件,如下所示,lib-input 和 lib-show-errors 是我在一个角度库中的组件我正在此应用中使用。
<form *ngIf="form" [formGroup]="form">
<div *ngFor="let ohFormGroup of form.controls;let i=index">
<div [formGroup]="ohFormGroup">
<ng-container *ngFor="let formField of ohFormGroup.controls;">
<div>
<div class="label">{{formField.label}}</div>
<lib-input [formControlName]="formField.name">
</lib-input>
</div>
<lib-show-errors *ngIf="isSubmitted && ohFormGroup.controls[formField.name].errors"
[formField]="ohFormGroup.controls[formField.name]"
[errorMessages]="formField.validation.errorMessages">
</lib-show-errors>
</ng-container>
</div>
</div>
</form>
我需要显示与 JSON 中 values 数组中返回的 person 对象相对应的控件。例如,如果 values 数组有 4 个对象,我需要显示四组全名、电话号码和电子邮件控件,它们是 JSON 中 fields 数组的一部分。如果用户想通过单击按钮添加第 5 个人,我应该为这 3 个控件动态生成一个表单组并显示它,然后在提交表单时我需要将所有 5 个对象发布到 API POST 端点。这是我的要求。
我在使用上述模板时遇到错误。他们是
“FormArray”类型缺少“FormGroup”类型中的以下属性:
解决方法
根据您想要的 JSON 结构,我将通过以下方式初始化您的表单组:
export class MyComponent extends OnInit {
@Input()
person: Person
formGroup: FormGroup
ngOnInit() {
this.formGroup = new FormGroup({
type: new FormControl(this.person.type),fields: new FormArray(
this.person.fields.map(t => {
return this.createField(t)
}
),values: new FormArray(
this.person.values.map(t => {
return this.createValue(t)
})
)
})
}
createField(field: Field) {
return new FormGroup({
name: new FormControl(field.name),label: new FormControl(field.label),validation: new FormGroup(validation)
})
},createValue(value: Value) {
return new FormGroup({
id: new FormControl(value.id),fullName: new FormControl(value.fullName),phoneNumber: new FormControl(value.phoneNumber),email: new FormControl(value.email)
})
}
}
您的模板可能如下所示:
<form *ngIf="formGroup" [formGroup]="formGroup">
<ng-container *ngIf="formGroup.get('fields'); let fields">
<div [formArray]="fields">
<div *ngFor="let field of fields.controls;let i = index">
<div [formGroupName]="i">
<div>
<div class="label">{{field.label}}</div>
<lib-input [formControlName]="field.name">
</lib-input>
</div>
<lib-show-errors [validation]="field.validation">
</lib-show-errors>
</div>
</div>
</div>
</ng-container>
</form>
,
您的 .html 有问题
首先,创建一个返回 FormGroup 的函数
group(index:number)
{
return this.form.at(index) as FormGroup
}
那你可以-我把代码用简单的输入-
<div *ngFor="let ohFormGroup of form.controls;let i=index">
<div [formGroup]="group(i)">
<!--see that you iterate over "formFiels" not over "ohFormGroup.controls"-->
<ng-container *ngFor="let formField of personFields">
<div>
<div class="label">{{formField.label}}</div>
<input [formControlName]="formField.name">
</div>
</ng-container>
</div>
</div>
是的,就像“丑陋的把戏”一样,让函数返回formGroup,但严格模式下的Angular不知道“ohFromGroup”是FormGroup还是FormControl
注意:关于你的 lib-show-errors,formField 应该有点像
[formField]="group(i).get(formField.name)"
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。