Search code examples
angularangular-materialformarray

Angular: Formarray inside Formarray not setting the values on FormControl


I have a form that contains a FormArray inside which you can dynamically add values ​​and in this case I can get the values ​​through the FormControl.

firstGroup = this._formBuilder.group({
dataArray: new UntypedFormArray([]),  });

Inside this first FormArray there is another FormArray that can also be added values, but in this second one, although it was able to change the values ​​through a selection box, the associated FormControl does not register the chosen value.

    const line = new UntypedFormGroup({
      chooseOption1: new UntypedFormControl('', Validators.required),
      secondDataArray: new UntypedFormArray([]),
    });
    this.firstGroup.controls.dataArray.push(line);
  }

  addInnerLine(i: any) {
    const control = <UntypedFormArray>(
      this.dataArray.controls[i].get('secondDataArray')
    );
    control.push(this.addInnerLineData());
  }

  addInnerLineData() {
    return new UntypedFormGroup({
      qtd: new UntypedFormControl(),
    });
  }

I think the problem is in the way I'm defining the table, but I've tried so many things and I still can't solve it.

            <table
              mat-table
              [dataSource]="dataArray.controls[i].value.secondDataArray"
              formArrayName="secondDataArray"
              class="mat-elevation-z8"
            >
              <ng-container matColumnDef="qtd">
                <th mat-header-cell *matHeaderCellDef>QTD</th>
                <td mat-cell *matCellDef="let row; let index = index">
                  <mat-form-field appearance="outline">
                    <mat-select formControlName="qtd" name="qtd">
                      <mat-option *ngFor="let ob of exampleData" [value]="ob">
                        {{ ob.symbol }}
                      </mat-option>
                    </mat-select>
                  </mat-form-field>
                </td>
              </ng-container>
              <tr mat-header-row *matHeaderRowDef="displayColumns"></tr>
              <tr mat-row *matRowDef="let row; columns: displayColumns"></tr>
            </table>

StackBlitz

Can anyone help me?


Solution

  • After many attempts and read and see lot of examples, i've found the solution.

    First i've created an aux array.

      auxDataSource: any = [];
    

    When I add a new inner line I turn the auxDataSource in a new MatTableDataSource

      addInnerLine(i: any) {
        const control = <UntypedFormArray>(
          this.dataArray.controls[i].get('secondDataArray')
        );
        control.push(this.addInnerLineData());
        this.dataSource[i] = control.controls;
        this.auxDataSource[i] = new MatTableDataSource(this.dataSource[i]);
      }
    

    And finally I changed the table on HTML to this:

              <ng-container formArrayName="secondDataArray">
                <mat-table *ngIf="auxDataSource[i]" [dataSource]="auxDataSource[i]">
                  <!-- Qtd Column -->
                  <ng-container matColumnDef="qtd">
                    <mat-header-cell *matHeaderCellDef> Qtd </mat-header-cell>
                    <mat-cell
                      *matCellDef="let element; index as t"
                      [formGroup]="element"
                    >
                      <mat-form-field appearance="outline">
                        <mat-select formControlName="qtd" name="qtd">
                          <mat-option
                            *ngFor="let sind of exampleData"
                            [value]="sind"
                          >
                            {{ sind.name }}
                          </mat-option>
                        </mat-select>
                      </mat-form-field>
                    </mat-cell>
                  </ng-container>
                  <mat-header-row
                    *matHeaderRowDef="displayColumns"
                  ></mat-header-row>
                  <mat-row *matRowDef="let row; columns: displayColumns"></mat-row>
                </mat-table>
              </ng-container>
    

    I've updated the Stackblitz