动态嵌套形式控制角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); 
    } 
} 
+0

谢谢@JackKoppa的回复。你的答案肯定会给我一些想法,以继续我的API响应。我还发现了另一个有用的Plunker链接 - https://plnkr.co/edit/hpuPdh?p=preview。再次感谢 – Maher

+0

抱歉,上面的链接是你的。我发现的是 - http://plnkr.co/edit/3k23R3z2KHlAXW5OLKRA?p=preview – Maher

+0

不错,那个plunk看起来也很适用。如果这个答案足够了,请随时将其标记为已接受,并告诉我您是否有其他问题 –