1

I am displaying a form array inside mat-table:

    <mat-table #table [dataSource]="dataSource" class="example-table"
        *ngIf="dataSource">
        <ng-container matColumnDef="invoice_id">
            <mat-header-cell *matHeaderCellDef>Invoice#</mat-header-cell>
            <mat-cell *matCellDef="let row">{{ row.invoice_id }}</mat-cell>
        </ng-container>

        <ng-container matColumnDef="update_status">

           <mat-header-cell *matHeaderCellDef>Update Status</mat-header-cell>

           <!-- <mat-cell *matCellDef="let row">{{ row.date_modified }}</mat-cell> -->

           <mat-cell *matCellDef="let row; let i = index;"
              formArrayName="status_array">
              <div [formGroupName]="i">
            <mat-form-field>
                <mat-label>Status</mat-label>
                <mat-select id="receipt_status"
                    formControlName="receipt_status" placeholder="Status">
                    <mat-option (click)="onChange(row, i, 'ms', status.id)"
                        *ngFor="let status of ReceiptStatus;"
                        [value]="status.id">
                        {{status.name}}
                    </mat-option>
                </mat-select>
            </mat-form-field>&nbsp;
        </div>
    </mat-cell>

</ng-container>

<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
            <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>

<mat-paginator #paginator [length]="length" [pageSize]="pageSize"
        [showFirstLastButtons]="true" [hidePageSize]="true"
        (page)="loadData($event)" *ngIf="dataSource && length > 0">
    </mat-paginator>
</div>

At the .ts script:

inside ngOnInit:

ngOnInit{

this.createStatusArray();

}

createStatusArray(){
    this.statusArrayForm = this.fb.group({
      'status_array': this.createArray()
    })

  }

  createArray(): FormArray {
    return new FormArray(this.dataSource.data.map(item => new FormGroup({
      receipt_status: new FormControl(item['is_active']),
    })));

  }

The dataSource is set from an api call:

if(response && response.status == "success"){
        this.receiptMsg = false;

        this.receiptsArray = response.response;
        this.length = this.receiptsArray.length;
        this.dataSource = response.response;
        // console.log(this.dataSource)
          setTimeout(() => {
            this.dataSource.paginator = this.paginator;
          }, 50);

The statuses added inside the *ngFor:

ReceiptStatus = [
    {id: 0, name: 'Inactive'},
    {id: 1, name: 'Active'}
  ];

I kept getting the following errors:

ERROR Error: Cannot find control with path: 'status_array -> 1'

0

1 Answer 1

3

You need create the formArray when you get the data, not in ngOnInit, futhermore is better that the dataSource of the mat-table was the formArray

  if(response && response.status == "success"){
        this.receiptMsg = false;
        this.receiptsArray = response.response;
        this.length = this.receiptsArray.length;
        this.dataAuxiliar=response.response; //<--use an array to store the data
        this.formArray = this.createArray(response.response);
          setTimeout(() => {
            this.dataSource.paginator = this.paginator;
          }); //is innecesary give a "time", If we make a setTimeout, angular 
              //make the instruction in a "second-round"

  //to createArray pass the data
   createArray(data:any[]): FormArray {
    return new FormArray(data.map(item => new FormGroup({
      receipt_status: new FormControl(item['is_active']),
    })));

After you can do

  <!--see that the dataSource is formArray.controls-->
  <!--it's not necesary that the formArray "belong" to a formGroup-->
  <!--if belong to a formGroup be sure that you has a getter like

     get formArray(){
       return this.form?this.form.get('myFormArray') as FormArray:null
     }
  -->
  <mat-table #table *ngIf="formArray" 
        [dataSource]="formArray.controls" class="example-table">
        <--for an element of dataAuxiliar use let i=index and
            dataAuxiliar[i].propertieOfThe data, e.g. -->
        <ng-container matColumnDef="invoice_id">
            <mat-header-cell *matHeaderCellDef>Invoice#</mat-header-cell>
            <mat-cell *matCellDef="let row;let i=index">{{ dataAuxiliar[i].invoice_id }}</mat-cell>
        </ng-container>

       <--for a control of the FormArray use 
              [formControl]=element.get('field of the formGroup')-->
        <ng-container matColumnDef="update_status">
           <th mat-header-cell *matHeaderCellDef> Status</th>
           <td mat-cell *matCellDef="let element">
               <input [formControl]="element.get('receipt_status')">
           </td>
         </ng-container>

An example of formArray in a mat-table can be founded in this SO question

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.