2016-06-24 12 views
35

Próbuję dynamicznie dodawać pola wejściowe, gdy użytkownik kliknie przycisk dodawania, a dla każdego pola formularza musi być przycisk usuwania, gdy użytkownik kliknie, że pola formularza muszą być usunięte, muszę osiągnąć to za pomocą kątowego 2, jak jestem nowy kątowy 2 proszę mi pomóc, aby zakończyć jąJak dynamicznie dodawać i usuwać pola formularza w Angular 2

Co próbowałem

ja stworzyliśmy zestaw pól (3 zaznacz pole i 1 pole tekstowe), utworzyłem przycisk o nazwie dodaj pola, ale próbowałem go w kanciastej 1.x działa dobrze, ale w kanciastej 2 nie wiem jak to zrobić, to jest link z mojej pełnej pracy

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

Możesz użyć 'ControlGroup' do osiągnięcia tego http://stackoverflow.com/questions/36627573/angular2-form-controlgroup-who-hold-an-undefined-number-of-control/36641967#36641967 –

+0

@A_Singh czy masz jakiś pomysł, dlaczego kąt 2 nie ładuje szablonu wewnętrznego kodu skryptu html –

+0

czy myślisz, że wstrzykiwanie skryptów przy użyciu '[innerHTML]' nie działa? To dlatego, że kątowe nie pozwala na wstrzykiwanie skryptów w ten sposób –

Odpowiedz

109

To jest kilka miesięcy późno, ale myślałem, że dostarczę moje rozwiązanie w oparciu o this here tutorial. Najważniejsze jest to, że o wiele łatwiej jest zarządzać, gdy zmienisz sposób podejścia do formularzy.

Najpierw użyj ReactiveFormsModule zamiast lub oprócz normalnego FormsModule. Za pomocą formularzy reaktywnych tworzysz formularze w komponentach/usługach, a następnie podłączasz je do swojej strony zamiast do strony generującej sam formularz. To trochę więcej kodu, ale jest o wiele bardziej testowalny, o wiele bardziej elastyczny i o ile mogę powiedzieć najlepszy sposób na tworzenie wielu nietrywialnych formularzy.

Wynik końcowy będzie wyglądać trochę tak, koncepcyjnie:

  • Masz jedną bazę FormGroup ze cokolwiek FormControl przypadki trzeba za całokształt postaci. Na przykład, tak jak w tutorialu, do którego się przyłączyłem, powiedzmy, że potrzebujesz formularza, w którym użytkownik może wpisać swoją nazwę raz, a następnie dowolną liczbę adresów. Wszystkie jednorazowe dane wejściowe będą znajdować się w tej podstawowej grupie formularzy.

  • Wewnątrz tej instancji FormGroup pojawi się jedna lub więcej instancji FormArray. A FormArray jest po prostu sposobem grupowania wielu kontrolek razem i iterowania nad nimi. Możesz także wstawić wiele instancji do swojej tablicy i użyć ich jako "mini-formularzy" zagnieżdżonych w większej formie.

  • poprzez zagnieżdżanie Multiple FormGroup i/lub FormControl instancji w dynamicznym FormArray można kontrolować ważność i zarządzania formularz jako jeden, duży, reaktywnej kawałku składa się z kilku części dynamicznych. Na przykład, jeśli chcesz sprawdzić, czy każde wejście jest poprawne przed zezwoleniem użytkownikowi na przesłanie, ważność jednego podformularza "spaprze" do formularza najwyższego poziomu, a cała forma staje się nieważna, co ułatwia zarządzać dynamicznymi wejściami.

  • Jako, że FormArray jest zasadniczo opakowaniem wokół interfejsu macierzowego, ale dla elementów formularza, można w dowolnym momencie przesuwać, popować, wstawiać i usuwać formanty bez odtwarzania formularza lub wykonywania złożonych interakcji.

W przypadku tutorial związany z idzie w dół, tutaj niektóre przykładowy kod można zaimplementować samemu (moje przykłady użyć maszynopis), które przedstawiają podstawowe idee:

kod podstawowy komponent:

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 
    } 
} 

podkomponent Kod (po jednym dla każdego nowego pola wejściowego, aby utrzymać wszystko czyste)

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 
} 

bazowa Składnik 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> 

podkomponentu HTML

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

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

W powyższym kodu Zasadniczo mają składnik stanowi podstawę formy, a następnie każdy z sub -component zarządza własnym instancją FormGroup wewnątrz FormArray znajdującym się wewnątrz bazy FormGroup. Szablon podstawowy przechodzi przez podgrupę do podkomponentu, a następnie można dynamicznie obsługiwać sprawdzanie poprawności dla całej formy.

Ponadto, łatwo jest zmienić kolejność komponentów poprzez ich strategiczne wstawianie i usuwanie z formularza. Działa z (na pozór) dowolną liczbą danych wejściowych, ponieważ nie są one w konflikcie z nazwami (duża wada formularzy opartych na szablonach, o ile mi wiadomo) i nadal zachowujesz prawie automatyczną walidację. Jedynym "minusem" tego podejścia jest, oprócz pisania nieco więcej kodu, trzeba się nauczyć jak działają formularze. Jednak otworzy to możliwości dla znacznie większych i bardziej dynamicznych form, jak to się dzieje.

Jeśli masz pytania lub chcesz wskazać błędy, śmiało. Właśnie napisałem powyższy kod w oparciu o coś, co zrobiłem sam w zeszłym tygodniu z nazwami zmienionymi i innymi misc. właściwości zostały pominięte, ale powinny być proste. Jedyną istotną różnicą między powyższym kodem a moim jest to, że przeniosłem całą budowę formularza do oddzielnej usługi, która jest wywoływana ze składnika, więc jest nieco mniej niechlujny.

+1

Jak zaimplementować ngModel do tego formularza? – elporfirio

+0

@elporfirio Nie używasz ngModel z tymi formularzami. ngModel jest używany głównie w przypadku dwukierunkowego powiązania danych z obiektem JavaScript. Te reaktywne formy są w zasadzie własnymi obiektami z różnymi przydatnymi polami i właściwościami, takimi jak walidacja. Zamiast tego otrzymujesz właściwość ".value" z formularza i jest to zestaw wyników. Możesz nim manipulować i mapować na dowolne klasy lub interfejsy, które posiadasz. –

+0

tak powyżej powyższego approch jest bardzo to działa dla mnie, ale nie wiem, jak zastosować niestandardową dyrektywę do powyższej rzeczy – Runali

Powiązane problemy