Angular 9 - différent formGroupName avec le même nom de formControlName affecte le même formControlName

Sep 15 2020

J'ai créé la variable form: FormGroup où j'ai défini le groupe avec un FormArray localizationData: FormArray comme ceci dans le constructeur de mon service:

this.form = this.formBuilder.group({
    localizationData: this.formBuilder.array([])
});

Ensuite, je pousse vers ce FormArray un FormGroup avec FormControl spécifique avec cette fonction:

addLocalizedFormGroup(locale?: any){
    locale = (locale == undefined) ? this.selectedLocale : locale;
    let formArray = <FormArray>this.form.get('localizationData');
    formArray.push(this.formBuilder.group({       
        locale: [locale.code],
        codelistName: ['', Validators.required]
    }));
    locale.created = true;
    this.createdLocales.push(locale);
}

Dans ngOnInit du composant, j'ai appelé cette fonction deux fois. Exemple de variable d'objet locale:

{ "code": "SK", "name": "Slovenčina" }

Pour afficher le format spécifique à l'utilisateur de cette locale, j'utilise cette fonction:

localeFormatter = (x: any) => x.code + " | " + x.name;

J'ai implémenté une liste d'options simple avec des localisations pour que l'utilisateur puisse en sélectionner une:

<div class="form-group col-3">
    <label>Lokalizácia
        <select class="form-control" [(ngModel)]="this.defservice.selectedLocale">
            <option *ngFor="let locale of this.defservice.createdLocales" [ngValue]="locale">{{this.defservice.localeFormatter(locale)}}</option>
        </select>
    </label>
</div>

Cette liste d'options fonctionne très bien. Lorsque je sélectionne une langue différente, le modèle change en tant qu'objet. Pour trouver un FormGroup par locale, je crée une fonction très simple pour cela:

localizationIndexOf(locale: any): number{
    return (<FormArray>this.form.get('localizationData')).controls.findIndex(x => x.get('locale').value == locale.code);
}

Et maintenant, le problème que je conteste est de montrer la valeur utilisateur de FormControl, codelistName, comme vous pouvez le voir défini dans la fonction addLocalizedFormGroup. Voici le html:

<ng-container [formGroup]="defservice.form">
    <ng-container formArrayName="localizationData">
        <ng-container [formGroupName]="defservice.localizationIndexOf(defservice.selectedLocale)">
            <div class="row">
                <div class="form-group col-2">
                    <label>Lokalizácia
                        <input type="text" class="form-control" [value]="defservice.localeFormatter(defservice.selectedLocale)"
                                disabled="true">
                    </label>
                </div>
                <div class="form-group col-10">
                    <label>Názov <span style="color: red">*</span>
                        <input type="text" class="form-control" formControlName="codelistName">
                     </label>
                </div>
            </div>
        </ng-container>
    </ng-container>
</ng-container>

Mais après avoir changé de langue dans la liste d'options, la valeur de localisation change correctement, localizationIndexOf (defservice.selectedLocale) renvoie un index correct mais après la modification de codelistName de tout index de FormmArray créé avec la fonction addLocalizedFormGroup, ce que j'ai ajouté, seul le premier (avec l'index 0) change . J'imprime toute la valeur de la forme et elle ne montre que la valeur modifiée de la première langue. Événement si j'ai 2 ou 10 langues. Je veux dire 2 ou 10 ont poussé FormGroups dans localizationData FormArray de la forme: FormGroup. Il semble que lors du premier chargement du composant, formGroup ne met jamais à jour sa valeur, je me réfère à cette ligne:

<ng-container [formGroupName]="defservice.localizationIndexOf(defservice.selectedLocale)">

Merci pour tout conseil.

Réponses

2 acorbeil Sep 16 2020 at 04:50

J'ai recréé le problème de mon côté mais je n'ai pas pu trouver de solution avec la *ControlName=''syntaxe. J'en ai trouvé un avec [formControl]=''mais il faudra oublier la formGroupNamehiérarchie.

Si vous pouvez conserver une référence de l'index du courant FormGroupdu localizationData: FormArray, vous pourrez récupérer le contrôle du tableau:

<input class="..." type="text" [formControl]="localizationData.at(currentLocaleIndex).get('codelistName')">

localizationData est un getter pour le FormArray:

get localizationData(): FormArray {
    return this.form.get('localizationData') as FormArray
  }

Et une solution pour se tenir currentLocaleIndexau courant est de mettre à jour la valeur lorsqu'un changement se produit sur le <select>genre:

<select (change)="updateCurrentLocaleIndex()" class="form-control" [(ngModel)]="this.defservice.selectedLocale">
  <option *ngFor="let locale of this.defservice.createdLocales" [ngValue]="locale">{{this.defservice.localeFormatter(locale)}}</option>
</select>

Dans votre classe de composants:

updateCurrentLocaleIndex() {
   this.currentLocaleIndex = this.localizationIndexOf(this.defservice.selectedLocale)
 }