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.
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 –
@A_Singh czy masz jakiś pomysł, dlaczego kąt 2 nie ładuje szablonu wewnętrznego kodu skryptu html –
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 –