首页 文章

动态嵌套表单控件Angular 2

提问于
浏览
3

我的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 : []
                })
            }),
        });

我不明白如何动态添加控件

1 回答

  • 2

    如果您想要完全匹配您的API响应,那么此处的结构最终会相当复杂 . 由于到目前为止,每个 attributes 属性只有一个属性对象,因此可能直接使 attributes 成为对象而不是对象数组,这将简化以下代码 . 下面的代码与您当前的API结构相匹配,可以在this working plunker播放 .

    要注意的一些事项:

    • FormGroup 需要是最外层的表单对象,也可用于保存不确定数量的 FormControl
      另一方面,当控件的数量不确定时,

    • FormArray 非常有用, and 这些控件的调用并不重要 .

    • 这就是为什么,下面, 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>
                    
    </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); } }

相关问题