alim1990
alim1990

Reputation: 4972

Angular 9 How to return only one drop down list form control name for each index of an array?

Based on the this stack overflow answer about generating formControlName for each extracted index of an array, I did the following:

Suppose we have and array of indexes called odkDataIndexes having lets say the following:

odkDataIndexes = ['id', 'name'];

So I need to generate 2 form controls with each having the correspondent names:

createIndexesForm(extractedIndexesArray): void {
  this.indexesForm = this.fb.group({
    mappingFieldItems: this.fb.array(
      extractedIndexesArray.map(values => {
        return this.fb.group(values);
      })
    )
  });
}

And then on button click, I need to generate the form controls:

async generateMappingFields() {
  this.showFields = false;
    if (this.odkDataIndexes.length > 0) {
      this.createIndexesForm(this.odkDataIndexes);
    }
  this.showFields = true;
}

At the HTML side I have the following:

<div *ngIf="showFields">
        <mat-spinner *ngIf="!indexesForm" value="50" class="setSpinnerOnTop" diameter="75" [color]="medair-color"></mat-spinner>
        <div [formGroup]="indexesForm" *ngIf="indexesForm">
            <div formArrayName="mappingFieldItems">
                <div *ngFor="let fg of indexesForm.get('mappingFieldItems').controls" [formGroup]="fg">
                    <ng-container *ngFor="let fc of fg.controls | keyvalue">
                        <!-- <input type="text" [formControl]="fc.value"> -->
                        <span></span>
                        <mat-form-field class="formFieldWidth" color="warn" appearance="fill">
                            <mat-label>{{fc.value | keyvalue}}</mat-label>
                            <mat-select [formControl]="fc.value">

                                <mat-option (click)="getName(fc.value, de.id, fg.controls)" *ngFor="let de of dataElementsDetails; let i = index;" [value]="de.id">
                                    {{de.code}}

                                </mat-option>
                            </mat-select>
                        </mat-form-field>
                    </ng-container>
                </div>
            </div>
        </div>
    </div>

Now for each index inside the odkDataIndexes, instead of showing only one drop down list per index, it is showing 7 or 8 depending on selected data.

The getName(fc.value, de.id, fg.controls) is retuning the following on click:

enter image description here

And this image shows that for only one index, there is 16 drop down list, and the last consoled value of fg.ccontrols contains 18 arrays.

enter image description here

I did a stackblitz with only the code in it.

Upvotes: 1

Views: 1134

Answers (1)

Muhammed Albarmavi
Muhammed Albarmavi

Reputation: 24424

I don't think you need to use reactive form array just a formGroup can work for you by generate formGroup base of dataIndexes value

component

createIndexesForm(extractedIndexesArray: string[]): void {
    // ["id", "name"] 👉  {id:null,name:null}
    const controls = extractedIndexesArray.reduce((g, k) => {
      g[k] = null;
      return g;
    }, {});

    this.indexesForm = this.fb.group({
      mappingFieldItems: this.fb.group(controls)
    });
  }

template

<div [formGroup]="indexesForm" *ngIf="indexesForm">
    <div [formGroup]="indexesForm.get('mappingFieldItems')">
        <div *ngFor="let controlName of dataIndexes">
            <mat-form-field class="formFieldWidth" color="warn" appearance="fill">
                <mat-label>{{controlName}}</mat-label>
                <mat-select [formControlName]="controlName">
                    <mat-option *ngFor="let de of dataElementsDetails; let i = index;" 
                        [value]="de">
                        {{de}}
                    </mat-option>
                </mat-select>
            </mat-form-field>

        </div>
    </div>
</div>

demo 🚀

Upvotes: 1

Related Questions