2016-06-24 55 views
35

表單字段我想動態,而用戶點擊添加按鈕輸入字段併爲每個表單字段必須有一個刪除按鈕,當用戶點擊該表單字段必須拆除,我要做到這一點使用角2,因爲我是新來的角2,請幫我把它完成如何動態地添加和刪除角2

我已經試過

我創建了一個集中的字段(3選擇框和1個文本框),創建了一個名爲添加字段按鈕,但我已經在角1.x中嘗試過它工作正常,但在2角我不知道如何去完成它,這是我的全部工作link

app/app.component.ts 
import { 
    Component 
    } 
from '@angular/core'; 
    @Component({ 
    selector: 'my-app', 
    template: ` 
    <h1>{{title}}</h1> 
    <div class="container"> 
    <button class="btn btn-success bt-sm">add</button> 
    <form role="form" calss="form-inline"> 
    <div class="form-group col-xs-3"> 
    <label>Select State:</label> 
    <select class="form-control" [(ngModel)]="rules.State" id="sel1"> 
      <option>State1</option> 
      <option>State2</option> 
      <option>State3</option> 
      <option>State4</option> 
</select> 
    </div> 
    <div class="form-group col-xs-3"> 
<label>Rule:</label> 
    <input type="text" data-toggle="modal" data-target="#myModal" class="form-     control"> 
    </div> 
<div class="form-group col-xs-3"> 
<label>Pass State :</label> 
    <select class="form-control" [(ngModel)]="rules.pass"> 
    <option>State1</option> 
    <option>State2</option> 
    <option>State3</option> 
    <option>State4</option> 
</select> 
</div> 
<div class="form-group col-xs-3"> 
    <label>Fail State:</label> 
     <select class="form-control" [(ngModel)]="rules.fail"> 
     <option>State1</option> 
     <option>State2</option> 
     <option>State3</option> 
    <option>State4</option> 
    </select> 
     </div> 
    </form> 
    </div> 
<div class="modal fade" id="myModal" role="dialog"> 
     <div class="modal-dialog"> 
      <div class="modal-content"> 
       <div class="modal-header"> 
        <button type="button" class="close" data-dismiss="modal">&times </button> 
        <h4 class="modal-title">Rules Configuration</h4> 
       </div> 
       <div class="modal-body"> 
       <p>Rules</p> 
       </div> 
       <div class="modal-footer"> 
       <button type="button" class="btn btn-default" data- dismiss="modal">Close</button> 
       </div> 
      </div> 

       </div> 
       </div> 
` 
    }) 
    export class AppComponent { 
      title = 'Rule Engine Demo'; 
      rules: Rules = { 
        State: '', 
        pass: '', 
       fail: '' 
       }; 
+1

你可以使用'ControlGroup'實現這個http://stackoverflow.com/questions/36627573/angular2-form-controlgroup-who-hold-an-undefined-number-of-control/36641967#36641967 –

+0

@A_Singh你有什麼想法爲什麼角2沒有加載模板HTML內部腳本代碼 –

+0

你的意思是使用'[innerHTML]注入腳本不起作用?這是因爲角度不允許以這種方式注入腳本 –

回答

109

這是幾個月晚,但我想我會提供基於this here tutorial我的解決方案。它的要點在於,一旦改變了你處理表單的方式,管理起來就容易多了。

首先,使用ReactiveFormsModule代替或除了正常FormsModule。使用被動式表單,可以在組件/服務中創建表單,然後將它們插入到頁面中,而不是生成表單本身的頁面。這是一個多一點的代碼,但它是一個很大的可測試性,靈活了許多,而據我可以告訴做了很多不平凡的形式的最佳方式。

最終的結果看起來有點像這樣,在概念上:

  • 你必須與任何FormControl情況下,你需要爲形式的一個整體底座FormGroup。例如,如同在我鏈接的教程中一樣,可以說你需要一個表單,用戶可以輸入一次他們的名字,然後輸入任意數量的地址。所有的一次性字段輸入將在這個基本形式組中。

  • 在那個FormGroup實例裏面會有一個或多個FormArray實例。 A FormArray基本上是將多個控件分組在一起並遍歷它們的一種方法。你也可以把多個FormGroup實例數組中,並使用你的嵌套形式更大範圍內那些本質上是「迷你形式」。

  • 通過動態FormArray內嵌套多個FormGroup和/或FormControl情況下,你可以控制的有效性和管理的形式,由多個動態部分之一,大,反應一塊。例如,如果您想在允許用戶提交之前檢查每個單一輸入是否有效,則一個子表單的有效性將「冒泡」到頂級表單並且整個表單變得無效,這使得管理動態輸入。

  • 由於FormArray本質上是一個數組接口的包裝,但是對於表單件,您可以隨時推送,彈出,插入和刪除控件,而無需重新創建表單或執行復雜的交互。

萬一我掛教程下降,這裏的一些示例代碼,你可以實現自己(我的例子中使用打字稿),其闡述的基本思路:

基礎組件代碼:

import { Component, Input, OnInit } from '@angular/core'; 
import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms'; 

@Component({ 
    selector: 'my-form-component', 
    templateUrl: './my-form.component.html' 
}) 
export class MyFormComponent implements OnInit { 
    @Input() inputArray: ArrayType[]; 
    myForm: FormGroup; 

    constructor(private fb: FormBuilder) {} 
    ngOnInit(): void { 
     let newForm = this.fb.group({ 
      appearsOnce: ['InitialValue', [Validators.required, Validators.maxLength(25)]], 
      formArray: this.fb.array([]) 
     }); 

     const arrayControl = <FormArray>newForm.controls['formArray']; 
     this.inputArray.forEach(item => { 
      let newGroup = this.fb.group({ 
       itemPropertyOne: ['InitialValue', [Validators.required]], 
       itemPropertyTwo: ['InitialValue', [Validators.minLength(5), Validators.maxLength(20)]] 
      }); 
      arrayControl.push(newGroup); 
     }); 

     this.myForm = newForm; 
    } 
    addInput(): void { 
     const arrayControl = <FormArray>this.myForm.controls['formArray']; 
     let newGroup = this.fb.group({ 

      /* Fill this in identically to the one in ngOnInit */ 

     }); 
     arrayControl.push(newGroup); 
    } 
    delInput(index: number): void { 
     const arrayControl = <FormArray>this.myForm.controls['formArray']; 
     arrayControl.removeAt(index); 
    } 
    onSubmit(): void { 
     console.log(this.myForm.value); 
     // Your form value is outputted as a JavaScript object. 
     // Parse it as JSON or take the values necessary to use as you like 
    } 
} 

子組件代碼:(每一個新的輸入字段,以保持乾淨的東西)

import { Component, Input } from '@angular/core'; 
import { FormGroup } from '@angular/forms'; 

@Component({ 
    selector: 'my-form-sub-component', 
    templateUrl: './my-form-sub-component.html' 
}) 
export class MyFormSubComponent { 
    @Input() myForm: FormGroup; // This component is passed a FormGroup from the base component template 
} 

基本組件HTML

<form [formGroup]="myForm" (ngSubmit)="onSubmit()" novalidate> 
    <label>Appears Once:</label> 
    <input type="text" formControlName="appearsOnce" /> 

    <div formArrayName="formArray"> 
     <div *ngFor="let control of myForm.controls['formArray'].controls; let i = index"> 
      <button type="button" (click)="delInput(i)">Delete</button> 
      <my-form-sub-component [myForm]="myForm.controls.formArray.controls[i]"></my-form-sub-component> 
     </div> 
    </div> 
    <button type="button" (click)="addInput()">Add</button> 
    <button type="submit" [disabled]="!myForm.valid">Save</button> 
</form> 

子組件HTML

<div [formGroup]="form"> 
    <label>Property One: </label> 
    <input type="text" formControlName="propertyOne"/> 

    <label >Property Two: </label> 
    <input type="number" formControlName="propertyTwo"/> 
</div> 

在上面的代碼我基本上具有表示形式的基部的組件,然後每個子組件在位於基地FormGroup內的FormArray內管理其自己的FormGroup實例。基本模板將子組傳遞給子組件,然後您可以動態地處理整個表單的驗證。

此外,這使得通過戰略性插入和從表單中刪除它們來重新排序組件成爲微不足道的。它可以與任何數量的輸入(看似)一起工作,因爲它們不會與名稱發生衝突(就我所知,它是模板驅動的表單的一大缺點),而且您仍然保留了非常多的自動驗證。這種方法唯一的「缺點」是,除了編寫更多的代碼外,你還必須重新學習表單如何工作。但是,隨着您的繼續,這將爲更大更動態的形式開闢可能性。

如果您有任何問題或想要指出某些錯誤,請繼續。我剛剛打了上面的代碼,根據我上個星期做了些什麼,改了名字和其他misc。遺漏的屬性,但它應該是直截了當的。上面的代碼和我自己的代碼之間唯一的主要區別是我將所有的表單構建移到了從組件調用的單獨服務中,所以它不那麼混亂。

+1

如何實現ngModel到那種形式? – elporfirio

+0

@elporfirio您不會在這些表單中使用ngModel。 ngModel主要用於處理與JavaScript對象的雙向數據綁定。這些反應形式本質上是他們自己的對象,具有各種有用的領域和屬性,如驗證。相反,您從表單中獲得「.value」屬性,這是您的結果集。你可以操縱它,然而你可以將它映射到你擁有的任何類或接口。 –

+0

是以上接近是非常適合我的,但我沒有得到如何將自定義指令應用於上述事情 – Runali