J'ai rencontré un problème lors de la réinitialisation de formGroup à partir du composant parent utilisé dans mon composant personnalisé. L'erreur que j'obtiens est:
Aucune instance FormControl n'est attachée à l'élément de contrôle de formulaire avec le nom: 'selectedCompany'
[~ # ~] html [~ # ~] :
<form [formGroup]="addForm">
...
<my-custom-component formControlName="selectedCompany"></my-custom-component>
...
</form
<my-custom-component>
est créé selon une méthode valide de création du composant formControl personnalisé: https://blog.ilsttram.io/angular/2016/07/27/custom-form-controls-in-angular-2.html# implementation-controlvalueaccessor
Composant
Voici le code qui initialise la variable formGroup addForm
:
let formTemp: any = {
selectedCompany: new FormControl(null, [Validators.required]),
}
this.addForm = this._formBuilder.group(formTemp);
La première fois que addForm
est initialisé tout va bien. Mais lorsque je rouvre modal où se trouve le formulaire et que le même code de composant est exécuté, l'erreur mentionnée ci-dessus se produit.
J'ai compris qu'il n'est pas bon de réinitialiser formGroup encore et encore, car le composant perd la référence à l'ancien formGroup.
Si vous devez définir des valeurs pour afficher une nouvelle forme, .setValue
est la solution ici:
Composant
Au lieu de réinitialiser addForm
, vérifiez si addForm
a été initialisé précédemment et si c'est le cas, définissez uniquement la valeur pour FormControls
existant:
if (this.addForm) {
this.addForm.setValue({
selectedCountry: null
})
} else {
let formTemp: any = {
selectedCompany: new FormControl(null, [Validators.required]),
}
this.addForm = this._formBuilder.group(formTemp);
}
De cette façon, je me suis dit que la référence n'est pas perdue pour l'ancien addForm
, donc aucune erreur ne se produit.
Ma solution est de remplacer formControlName
par formControl
.
Au lieu de
<my-custom-component formControlName="selectedCompany"></my-custom-component>
utilisation
<my-custom-component [formControl]="addForm.controls['selectedCompany']"></my-custom-component>
ou avec une méthode getMethod pour prendre formControl
Fonctionne également avec erreur:
Aucune instance FormControl n'est attachée à l'élément de contrôle de formulaire avec chemin
où j'ai utilisé du FormArray
.
J'ai trouvé une "solution" bizarre à cela. Donc, pour réinitialiser les sous-composants, qui utilisent le formGroup et deviennent confus lorsque vous les échangez. J'utilise ce hack.
comp.ts
public flicker: boolean = false;
reInit() {
this.flicker = true;
this.addForm = this._formBuilder.group({
selectedCompany: new FormControl(null, [Validators.required]),
});
setTimeout( () => this.flicker = false, 200); //On very heavy pages, timeout ensures that the flicker hack works as expected.
}
comp.html
<form [formGroup]="addForm" *ngIf="!flicker">
...
<my-custom-component formControlName="selectedCompany"></my-custom-component>
...
</form>
Un hack horrible, qui impose essentiellement aux composants formGroup de se détruire et de se réinitialiser, mais les temps désespérés appellent des mesures désespérées ...
J'avais besoin de ce hack, car j'utilise des objets FormGroup pour enregistrer les résultats d'un formulaire dans un tableau intermédiaire de résultats, chacun pouvant être rouvert et modifié à volonté. À l'avenir, je ferai une sauvegarde de l'état des formulaires basée sur ngModel, pour éviter ce problème, mais une solution temporaire est là.
setTimeout( () => this.flicker = false, 200); //On very heavy pages, timeout ensures that the flicker hack works as expected.
Il y a une meilleure façon de faire le scintillement de manière synchrone
this.flicker = true;
this._changeDetectorRef.detectChanges();
this.flicker = false;
this._changeDetectorRef.detectChanges();
détecter les modifications exécutera la détection des modifications de manière synchrone et mettra à jour la vue, supprimant ainsi l'ancien groupe de formulaires.