Reputation: 4972
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>
</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'
Upvotes: 1
Views: 2079
Reputation: 57909
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
Upvotes: 3