背景:
我正在尝试制作一个三层的表单前端,用户应该能够填写基本的细节以及带有标题的列表对象。整个列表需要是一个数组,用户除了可以添加单独的嵌套列表项之外,还可以添加该数组来创建新列表:
我正在使用Angular Form Group和Form Arrays来尝试实现这一点:
所需表单输入/数据结构:
这就是我想要实现的数据结构:
{ "name": "", "email": "", "list":
[ { "list_title": "",
"list_items": [ { "list_item_1": {}, "list_item_2": {} } ] }
] }
在上面,您可以看到要捕获的所需数据。在外部形式中,您可以看到三个字段。我想在列表字段中嵌套列表标题和列表项。列表项是嵌套在其中的另一个数组。其想法是到达用户可以添加项目并列出具有新项目等的对象的位置。。,
到目前为止的代码
我决定在两个组件中完成这项工作,并且能够访问外部项,但很难访问内部数组以进行数据绑定。
父组件html:
<p>form-comp works!</p>
<div class="form-container">
<form (ngSubmit)="submit()" [formGroup]="myForm">
<h1>User Registration</h1>
<div class="form-group">
<label for="firstname"></label>`
<input type="text" placeholder="First Name" formControlName="name" />
<input type="text" placeholder="Surname" formControlName="email" />
<br />
<div formArrayName="list">
<ng-container *ngFor="let myList of listArray.controls; index as i">
<div [formGroupName]="i">
<input
type="text"
name="firstname"
placeholder="List Title"
formControlName="name"
formControlName="list_title"
/>
<br />
</div>
<!-- // map items here -->
<app-products></app-products>
</ng-container>
<button (click)="addList()">Add List</button>
</div>
<button type="submit">Submit</button>
</div>
<br />
<div class="form-check">
{{ myForm.value | json }}
<br />
{{ myForm.valid | json }}
</div>
</form>
</div>
母公司tsx
export class FormCompComponent implements OnInit {
myForm!: FormGroup;
constructor (private fb : FormBuilder) {
}
ngOnInit(): void {
this.myForm = new FormGroup({
name: new FormControl('', Validators.required),
email: new FormControl('', Validators.required),
list: new FormArray([this.initListFormGroup()]),
});
}
addList() {
this.listArray.push(this.initListFormGroup());
}
initListFormGroup() {
return new FormGroup({
list_title: new FormControl('', Validators.required),
list_items: new FormArray([ ProductsComponent.addListItem()])
});
}
get listArray() {
return this.myForm.get('list') as FormArray;
}
submit() {
console.log(this.myForm.value);
}
}
通过上面的代码,我可以将新的列表父组推送到数组中,并通过循环这些精细的操作进行数据绑定。我还在子组件上调用一个静态方法,用生成一个新项目
ProductsComponent.addListItem()
子组件html:
<form [formGroup]="childForm">
<input type="text" name="list_item" placeholder="List Item" formControlName="name" formControlName="list_item_1" />
</form>
导出类产品组件{
@Input()
public childForm!: FormGroup;
constructor() {}
static addListItem(): FormGroup {
return new FormGroup({
list_item_1: new FormGroup(''),
list_item_2: new FormGroup(''),
});
}
}
到目前为止,我已经能够生成我的数据结构,当我返回myForm.value
时,可以在屏幕上看到这一点。但是,很难在子数组上进行映射:
<!-- // map items here -->
<app-products></app-products>
上面是我认为我需要映射内部数组的地方,但不确定返回该数组的等效函数是什么,因为它本质上是被隐藏的。
以下是我的用例开始偏离的步骤的参考教程:
https://youtu.be/DEuTcG8DxUI?t=652
如果这个问题有意义,请告诉我,我很想解决它,谢谢!
这看起来可能很复杂,但其概念与您在父窗体中使用FormArray
的内容相似,您需要确保您需要提供FormGroup
索引来呈现数组中的嵌套对象。
<!-- // map items here -->
<ng-container formArrayName="list_items">
<ng-container
*ngFor="
let listItem of getListItemArrayFromList(i).controls;
index as j
"
>
<app-products [childForm]="asListItemFormGroup(listItem)"></app-products>
</ng-container>
</ng-container>
<button (click)="addListItem(i)">Add List Item</button>
getListItemArrayFromList(i: number) {
return (this.listArray.get(`${i}`) as FormGroup).get(
'list_items'
) as FormArray;
}
asListItemFormGroup(listItem: AbstractControl) {
return listItem as FormGroup;
}
addListItem(formGroupIndex: number) {
this.getListItemArrayFromList(formGroupIndex).push(
ProductsComponent.addListItem()
);
}
请注意,根据您提供的数据,list_item_1
和list_item_2
是对象,因此您应该使用formGroupName
属性而不是formControlName
属性,并使用FormControl
创建FormGroup
模板。
<form [formGroup]="childForm">
<input
type="text"
name="list_item"
placeholder="List Item 1"
formGroupName="list_item_1"
/>
<input
type="text"
name="list_item"
placeholder="List Item 2"
formGroupName="list_item_2"
/>
</form>
StackBlitz 演示