Angular 9 - different formGroupName with same name of formControlName affects same formControlName

Viewed 1848

I created form: FormGroup variable where I defined group with a FormArray localizationData: FormArray like this in constructor of my service:

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

Then I pushing to that FormArray a FormGroup with specific FormControl with this function:

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);
}

In ngOnInit of component I called that function twice. Example of locale object variable:

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

To show to user specific format of that locale I using this function:

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

I implemented simple options list with localizations for user to select one:

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

That options list works fine. When I select different language, model change as a object. To find a FormGroup by locale I create very simple function for that:

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

And now, the problem what I am challenging is to show user value of FormControl, codelistName, as you can see defined in function addLocalizedFormGroup. Here is 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>

But after switch language in option list, localization value change correctly, localizationIndexOf(defservice.selectedLocale) return correct index but after edit codelistName of any index of FormmArray created with function addLocalizedFormGroup, what I added, only first one (with index 0) is changing. I print whole value of form and it show only changed value of first language. Event if I have 2 or 10 languages. I mean 2 or 10 pushed FormGroups into localizationData FormArray of form: FormGroup. It seems like on first load of component, formGroup never update his value, I ref to this line:

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

Thank you for any advice.

1 Answers

I recreated the problem on my side but was unable to find a solution with *ControlName='' syntax. I found one with [formControl]='' but you will have to forget the formGroupName hierachy.

If you can keep a reference of the index of the current FormGroup of the localizationData: FormArray, you will be able to get the control from the array:

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

localizationData is a getter for the FormArray:

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

And a solution to keep currentLocaleIndex up to date is to update the value when a change happens on the <select> like this:

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

In your component class :

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