2017-09-13 187 views
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 : [] 
       }) 
      }), 
     }); 

我不明白如何動態添加控件

回答

1

如果您想精確匹配您的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看起來也很適用。如果這個答案足夠了,請隨時將其標記爲已接受,並告訴我您是否有其他問題 –