web-dev-qa-db-fra.com

Composant personnalisé rupture de FormControl en cas de réinitialisation de FormGroup à partir du parent

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.

16
Mario Petrovic

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.

18
Mario Petrovic

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.

9
zucker

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à.

Modifier 1

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.

2
Karl Johan Vallner