0

I'm trying to do an Angular Material Table with Form Array, but I'm getting the error:

Could not find column with id "position".

I saw a lot of answers about the directive matColumnDef, but I have this at my code. Like this one and the name is the same with the dataSource. Like this one

   <ng-container matColumnDef="position">
                  <th mat-header-cell *matHeaderCellDef> No. </th>
                  <td mat-cell *matCellDef="let element" [formControlName]='arrayOfProperties[0]' > {{element.position}} </td>
              </ng-container>

You can see my code here: https://stackblitz.com/edit/angular-tyu1y4?file=src/main.ts

you can find the error at the browser console

I think it'something about the way that I am building the table here:

<div formArrayName="tourTable" *ngFor="let controls of tourTable.controls; let i = index;">
          <div [formGroupName]="i">
paulotarcio
  • 461
  • 1
  • 5
  • 20

1 Answers1

1

Mannage a FormArrray with a mat-table it's not equal than another table.

The simpler way is use as dataSource: tourTable.controls. Yes, we can use an array to "feed" the dataSource, so we are using an array of FormGroups (that really is a formArray.controls)

As we know the elements are formGroups, so we can use this in our td

<ng-container matColumnDef="position">
   <th mat-header-cell *matHeaderCellDef > No. </th>

   <!--see how we say that we are using as formGroup the "element"-->
   <td mat-cell *matCellDef="let element" [formGroup]="element">

        <input [formControlName]='arrayOfProperties[0]' >
   </td>
</ng-container>

Yes it's a bit "bizarro" repeat the [formGroup] in each element, the another way is create a function that return the formControl at index

getControl(index:number,name:string)
{
   return this.tourTable.at(index).get(name) as FormControl
}

And use [FormControl]instead of formControlName

<ng-container matColumnDef="position">
   <th mat-header-cell *matHeaderCellDef > No. </th>

   <td mat-cell *matCellDef="let element;let index=index" >

        <input [formControl]='getControl(index,arrayOfProperties[0])' >
   </td>
</ng-container>

NOTE: Don't forget use this.table.renderRows() when add a new element to the array

NOTE2: I'm not prety sure if was necessary in strict mode use a getter to the controls

  get controls(){
    return this.tourTable.controls as FormGroup[]
  }

And use

<table mat-table [dataSource]="controls">

stackblitz

Eliseo
  • 50,109
  • 4
  • 29
  • 67
  • with this code, how I can find the index from the table so I can use at the method remove? – paulotarcio Feb 22 '23 at 10:49
  • I can t have the dataSource equal the controls because my Data is diferent, with different name of propertis, from my Reactive Form. So I need to keep both – paulotarcio Feb 22 '23 at 15:05
  • Another Question: How can I bind some data without beeing in Input – paulotarcio Feb 22 '23 at 22:46
  • you can get the index using `let index=index` in the td with *matCellDef: `{{index}}`. This allow you call to `remove(index)` or if you has an array with the same number of elements write `{{myArray[index]}}` – Eliseo Feb 23 '23 at 06:57