Angular 动态嵌套窗体控件角度2

Angular 动态嵌套窗体控件角度2,angular,angular2-forms,angular2-formbuilder,angular-forms,Angular,Angular2 Forms,Angular2 Formbuilder,Angular Forms,我的API响应如下 "groups": [{ "group_name": "GRP1" "attributes": [{ "attribute_id": 1, "attribute_name": "Frequency", "value_reference": "tag"

我的API响应如下

"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"
                      }]
              }]  
--如何在Angular 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结构相匹配,可以在中使用

要记住的一些事情:

  • FormGroup
    需要是最外层的表单对象,也可以用来保存数量不确定的
    FormControl
  • 另一方面,当控件的数量不确定时,
    FormArray
    很有用,并且这些控件的名称无关紧要
  • 这就是为什么在下面,
    allGroups
    是一个包含最大组的数组,
    attributes
    是一个包含属性对象的数组,但这些属性对象本身就是组,因为我们希望能够根据它们的API属性名来命名控件
还有一个很好的机会就是这个结构不是你想要的(例如,也许你不希望所有这些值都是可编辑的
字段),但是它应该给你一个在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);
    }
}
从'@angular/core'导入{Component};
从'@angular/forms'导入{FormGroup,FormControl,FormArray,FormBuilder};
接口APIGroup{
“组名称”:字符串;
“属性”:数组
}
接口组属性{
'attribute_id':编号;
“属性名称”:字符串;
“值\引用”:字符串;
'值\静态\类型'?:字符串;
}
@组成部分({
选择器:“应用程序子项”,
模板:`
我是孩子

{{editTemplateForm.value | json}} `, }) 导出类子组件{ 建造师( 私人fb:FormBuilder ) { } sampleData:数组=[ { “组名称”:“GRP1”, “属性”:[{ “属性_id”:1, “属性名称”:“频率”, “值\参考”:“标记” }] }, { “集团名称”:“GRP2”, “属性”:[{ “属性_id”:2, “属性名称”:“日期”, “价值参考”:“静态”, “值\静态\类型”:“日期” }] } ] editTemplateForm:FormGroup; 恩戈尼尼特(){ this.editTemplateForm=this.fb.group({ 所有组:this.fb.array([]) }); //将调用对实际api数据的订阅 this.sampleData.forEach(组=>{ (this.editTemplateForm.get('allGroups')) .push(this.initGroup(group)); }); } initGroup(apiGroup:apiGroup):FormGroup{ 让formGroup=this.fb.group({ groupName:[apiGroup.group\u name], 属性:this.fb.array([]) }); apiGroup.attributes.forEach(attributeGroup=>{ (formGroup.get('attributes')) .push(this.initAttributeGroup(attributeGroup)); }); 返回表单组; } initAttributeGroup(属性:GroupAttributes):FormGroup{ 设formGroup=this.fb.group({}); Object.keys(attributes).forEach(name=>{ addControl(名称,新FormControl(属性[名称]); }); 返回表单组; } KeyOfforMgroup(组:FormGroup):数组{ 返回对象键(组控件); } }
谢谢@JackKoppa的回复。你的回答肯定给了我一些想法来继续我的API响应。我还发现了另一个有用的Plunker链接-。再次感谢,以上链接是您的。我发现很好,plunk看起来也很适用。如果这个答案足够,请随时将其标记为已接受,如果您有任何其他问题,请告诉我。Y@JackKoppa您知道我如何将新表单组控件添加到“属性”中吗?单击按钮时,我需要添加组和新属性行。我设法添加了新的组,但不知道如何添加属性应该像
formArray.push()
一样简单,传入新的
FormGroup
。让我尝试用这种按钮更新plunk