Home > Software engineering >  How to dynamically change the name of FormControls in FormArray
How to dynamically change the name of FormControls in FormArray

Time:03-30

I'm dynamically adding rows each with three select menus in my angular project and I need to access the values of them in the component ts file.
Right now the select menus are named Col1, Comparator, Col2. When I add another row, the menus in the 2nd row are named the same. That's a problem. How can I change it to a dynamic naming? Like row 1 has Col1-a, Comparator-a, Col2-a
row 2 has Col1-b, Comparator-b, Col2-b

component html:

<div  [formGroup]="form">


    <ng-container formArrayName="block">

        <ng-container *ngFor="let blockForm of block.controls; let j = index">

   
                <div  [formGroupName]="j">


        <mat-form-field  [style.width.px]=150 [style.margin-left.px]=10 appearance="fill">
            <mat-select  formControlName="Col1" (click)="getCols()" placeholder="select column 1">
                <mat-option  *ngFor="let i of DfCols" [value]="i" >{{i}}</mat-option>
             </mat-select>
            </mat-form-field>

            <mat-form-field  [style.width.px]=100 [style.margin-left.px]=10 appearance="fill">
                <mat-select  formControlName="Comparator" placeholder="comparator">
                    <mat-option  *ngFor="let com of comparator" [value]="com" >{{com}}</mat-option>
                 </mat-select>
                </mat-form-field>

                <mat-form-field  [style.width.px]=150 [style.margin-left.px]=10 appearance="fill">
                    <mat-select  formControlName="Col2" (click)="getCols()" placeholder="select column 2">
                        <mat-option  *ngFor="let i of DfCols" [value]="i" >{{i}}</mat-option>
                     </mat-select>
                    </mat-form-field>
                    
               
                    <app-button [style.margin-left.px]=0  color="grey" text="test" (btnClick)="test()"></app-button>
                    <app-button [style.margin-left.px]=0  color="salmon" text="Delete condition block" (btnClick)="deleteblock(j)"></app-button>
                    
    </div>

</ng-container>

</ng-container>
<app-button [style.margin-left.px]=0  color="lightblue" text="Add condition block" (btnClick)="addblock()"></app-button>


</div>

component ts:

export class FormgroupStrategyComponent implements OnInit {

  DfCols!:any;
  comparator = ['>', '>=', '<', '<=', '==', '!=']


  form = this.fb.group({
      block: this.fb.array([])
  });

  constructor(private fb:FormBuilder, private calculationService: DfCalculationService) { }


  get block() {
    return this.form.controls["block"] as FormArray;
  }

  addblock() {

    const blockForm = this.fb.group({
      Col1: ['', Validators.required],
      Comparator: ['', Validators.required],
      Col2:  ['', Validators.required]
    });
    this.block.push(blockForm)
  }

  deleteblock(blockIndex: number) {
    this.block.removeAt(blockIndex);
  }

CodePudding user response:

You could just keep a counter to give a unique id to each group. You can nest each group inside the main group.

  form = new FormGroup({});

  get groups() {
    return Object.keys(this.form.controls);
  }

  constructor(private fb: FormBuilder) {}

  deleteblock(blockId: string) {
    this.form.removeControl(blockId);
  }

  counter = 0;
  addblock() {
    const id = this.counter  ;
    const blockForm = this.fb.group({
      Col1: ['', Validators.required],
      Comparator: ['', Validators.required],
      Col2: ['', Validators.required],
    });
    this.form.addControl(id.toString(), blockForm);
  }
<form [formGroup]="form">
  <div *ngFor="let group of groups" [formGroupName]="group">
    <mat-form-field>
      <mat-select formControlName="Col1"></mat-select>
    </mat-form-field>

    <mat-form-field>
      <mat-select formControlName="Comparator"> </mat-select>
    </mat-form-field>

    <mat-form-field>
      <mat-select formControlName="Col2"> </mat-select>
    </mat-form-field>

    <button (click)="deleteblock(group)">DELETE</button>
  </div>
  <button (click)="addblock()">ADD</button>
</form>

Since each group has their own id, the form controls will have their own namespace. FormGroup.get() supports an array of strings to get a control from a nested group

this.form.get(['2', 'Col1']);
  • Related