动态嵌套形式控制角2
问题描述:
我的API响应等动态嵌套形式控制角2
"groups": [{
"group_name": "GRP1"
"attributes": [{
"attribute_id": 1,
"attribute_name": "Frequency",
"value_reference": "tag"
}]
},
{
"group_name": "GRP2"
"attributes": [{
"attribute_id": 2,
"attribute_name": "Date",
"value_reference": "static",
"value_static_type": "date"
}]
}]
- 我怎样才能在角4创建formConrol像
GroupName
List of Group's Attribute
GroupName
List of Group's Attribute
我的初始形式的控制显示数据是像
this.editTemplateForm = this.fb.group({
groups: this.fb.group({
group_name: ['', Validators.required ],
attributes : this.fb.group({
value_reference : []
})
}),
});
我不明白如何动态添加控件
答
如果您想精确匹配您的API响应,此处的结构相当复杂。因为到目前为止,每个attributes
属性都只有一个属性对象,所以您可以直接将attributes
设为对象,而不是一组对象,这将简化以下代码。下面的代码与您当前的API结构相匹配,可以在this working plunker上播放。
有些事情要记住:
-
FormGroup
需要在最外层的形式对象,也可以用来装FormControl
项目 -
FormArray
一个不确定的数字,在另一方面当控件的数量不确定时,它是很有用的,和这些控件的调用并不重要。 - 这就是为什么,下面的
allGroups
是一个拥有最大组的数组,而attributes
是一个拥有属性对象的数组,而这些属性对象本身就是组 - 因为我们希望能够根据它们的API命名控件属性名
也有一个很好的机会,这种结构是不准确你正在寻找(例如,也许你不希望所有这些值可编辑<input>
字段),但它应该能给你带来什么一个强大的基础,可以在plunker上玩,并且了解如何基于不断变化的表单对象动态生成HTML。
import {Component} from '@angular/core';
import {FormGroup, FormControl, FormArray, FormBuilder} from '@angular/forms';
interface APIGroup {
'group_name': string;
'attributes': Array<GroupAttributes>
}
interface GroupAttributes {
'attribute_id': number;
'attribute_name': string;
'value_reference': string;
'value_static_type'?: string;
}
@Component({
selector: 'app-child',
template: `
<div>
<h3>I'm the Child component</h3>
</div>
<form [formGroup]="editTemplateForm">
<div formArrayName="allGroups">
<div *ngFor="let group of editTemplateForm.get('allGroups').controls; let i=index" [formGroupName]="i">
<input formControlName="groupName" />
<div formArrayName="attributes">
<div *ngFor="let attributeGroup of group.get('attributes').controls; let n=index" [formGroupName]="n">
<input *ngFor="let key of keysOfFormGroup(attributeGroup)" [formControlName]="key" />
</div>
</div>
<br/>
</div>
</div>
</form>
<pre style="background: #ddd">{{editTemplateForm.value | json}}</pre>
`,
})
export class ChildComponent {
constructor(
private fb: FormBuilder
) { }
sampleData: Array<APIGroup> = [
{
"group_name": "GRP1",
"attributes": [{
"attribute_id": 1,
"attribute_name": "Frequency",
"value_reference": "tag"
}]
},
{
"group_name": "GRP2",
"attributes": [{
"attribute_id": 2,
"attribute_name": "Date",
"value_reference": "static",
"value_static_type": "date"
}]
}
]
editTemplateForm: FormGroup;
ngOnInit() {
this.editTemplateForm = this.fb.group({
allGroups: this.fb.array([])
});
// would call on a subscription to actual api data
this.sampleData.forEach(group => {
(<FormArray>this.editTemplateForm.get('allGroups'))
.push(this.initGroup(group));
});
}
initGroup(apiGroup: APIGroup): FormGroup {
let formGroup = this.fb.group({
groupName: [apiGroup.group_name],
attributes: this.fb.array([])
});
apiGroup.attributes.forEach(attributeGroup => {
(<FormArray>formGroup.get('attributes'))
.push(this.initAttributeGroup(attributeGroup));
});
return formGroup;
}
initAttributeGroup(attributes: GroupAttributes): FormGroup {
let formGroup = this.fb.group({});
Object.keys(attributes).forEach(name => {
formGroup.addControl(name, new FormControl(attributes[name]));
});
return formGroup;
}
keysOfFormGroup(group: FormGroup): Array<string> {
return Object.keys(group.controls);
}
}
谢谢@JackKoppa的回复。你的答案肯定会给我一些想法,以继续我的API响应。我还发现了另一个有用的Plunker链接 - https://plnkr.co/edit/hpuPdh?p=preview。再次感谢 – Maher
抱歉,上面的链接是你的。我发现的是 - http://plnkr.co/edit/3k23R3z2KHlAXW5OLKRA?p=preview – Maher
不错,那个plunk看起来也很适用。如果这个答案足够了,请随时将其标记为已接受,并告诉我您是否有其他问题 –