C'est avec quelques mois de retard, mais j'ai pensé que je pourrais fournir une solution basée sur les éléments suivants ce tutoriel ici . L'essentiel est qu'il est beaucoup plus facile à gérer lorsque l'on change sa façon d'aborder les formulaires.
D'abord, utilisez ReactiveFormsModule
au lieu ou en plus de la méthode normale FormsModule
. Avec les formulaires réactifs, vous créez vos formulaires dans vos composants/services, puis vous les insérez dans votre page au lieu que celle-ci génère le formulaire lui-même. C'est un peu plus de code mais c'est beaucoup plus testable, beaucoup plus flexible, et pour autant que je sache, c'est la meilleure façon de créer beaucoup de formulaires non triviaux.
Le résultat final ressemblera un peu à ceci, conceptuellement :
-
Vous avez une base FormGroup
avec ce que FormControl
instances dont vous avez besoin pour l'ensemble du formulaire. Par exemple, comme dans le tutoriel dont j'ai donné le lien, disons que vous voulez un formulaire où un utilisateur peut saisir son nom une fois, puis un nombre quelconque d'adresses. Toutes les entrées de champ uniques se trouveraient dans ce groupe de formulaires de base.
-
A l'intérieur de ce FormGroup
instance, il y aura un ou plusieurs FormArray
instances. A FormArray
est essentiellement un moyen de regrouper plusieurs contrôles et d'itérer sur eux. Vous pouvez également mettre plusieurs FormGroup
dans votre tableau et utilisez-les comme des "mini-formulaires" imbriqués dans votre grand formulaire.
-
En emboîtant plusieurs FormGroup
et/ou FormControl
au sein d'un groupe dynamique FormArray
Avec l'outil de gestion des formulaires, vous pouvez contrôler la validité et gérer le formulaire comme une seule grande pièce réactive composée de plusieurs parties dynamiques. Par exemple, si vous souhaitez vérifier la validité de chaque entrée avant de permettre à l'utilisateur d'envoyer le formulaire, la validité d'un sous-formulaire se répercutera sur le formulaire de niveau supérieur et l'ensemble du formulaire deviendra invalide, ce qui facilite la gestion des entrées dynamiques.
-
En tant que FormArray
est essentiellement une enveloppe autour d'une interface de tableau, mais pour les éléments de formulaire, vous pouvez pousser, faire sauter, insérer et retirer des contrôles à tout moment sans recréer le formulaire ou effectuer des interactions complexes.
Au cas où le tutoriel dont je vous ai donné le lien ne fonctionnerait pas, voici quelques exemples de code que vous pouvez mettre en œuvre vous-même (mes exemples utilisent TypeScript) et qui illustrent les idées de base :
Code du composant de base :
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
}
}
Code du sous-composant : (un pour chaque nouveau champ de saisie, pour garder les choses propres)
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
}
Composant de base 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>
Sous-composant HTML
<div [formGroup]="form">
<label>Property One: </label>
<input type="text" formControlName="propertyOne"/>
<label >Property Two: </label>
<input type="number" formControlName="propertyTwo"/>
</div>
Dans le code ci-dessus, j'ai essentiellement un composant qui représente la base du formulaire, puis chaque sous-composant gère son propre FormGroup
au sein de la FormArray
situé à l'intérieur de la base FormGroup
. Le modèle de base transmet le sous-groupe au sous-composant, puis vous pouvez gérer la validation de l'ensemble du formulaire de manière dynamique.
De plus, cela permet de réorganiser facilement les composants en les insérant et en les retirant stratégiquement du formulaire. Cela fonctionne avec (apparemment) n'importe quel nombre d'entrées, car elles n'entrent pas en conflit avec les noms (un gros inconvénient des formulaires basés sur des modèles, pour autant que je sache) et vous conservez une validation pratiquement automatique. Le seul "inconvénient" de cette approche est que, outre l'écriture d'un peu plus de code, vous devez réapprendre le fonctionnement des formulaires. Cependant, cela ouvrira des possibilités pour des formulaires beaucoup plus grands et plus dynamiques au fur et à mesure.
Si vous avez des questions ou si vous voulez signaler des erreurs, n'hésitez pas. J'ai juste tapé le code ci-dessus basé sur quelque chose que j'ai fait moi-même la semaine dernière avec les noms changés et d'autres propriétés diverses laissées de côté, mais cela devrait être simple. La seule différence majeure entre le code ci-dessus et le mien est que j'ai déplacé toute la construction du formulaire vers un service séparé qui est appelé à partir du composant, de sorte que c'est un peu moins désordonné.
1 votes
Vous pouvez utiliser
ControlGroup
pour y parvenir stackoverflow.com/questions/36627573/0 votes
@A_Singh avez-vous une idée de la raison pour laquelle angular 2 ne charge pas les codes internes script du template html.
0 votes
Vous voulez dire injecter des scripts en utilisant
[innerHTML]
ne fonctionne pas ? C'est parce qu'Angular ne permet pas d'injecter des scripts de cette façon.0 votes
Pas les balises script, vous avez déjà utilisé jquery query builder ?
0 votes
query builder
? Non, mais cela se produit aussi parce qu'angular n'autorise pas les scripts dans les templates. voir cette question0 votes
Alors où je peux charger les balises script, si je charge dans index.html j'obtiens une erreur comme type indéfini, si je dois utiliser le script à l'intérieur du modèle n'importe quelle idée u ont