I am displaying the mat -table inside a loop. The records are displaying correctly and sorting arrows are also displayed. I've used MatSort
but it is not working. Can anyone help me out where I am getting wrong?
Here is my code.
HTML:
<div *ngFor="let rc of filteredSizeCode; let i = index" class="table-responsive table-content">
<h3 class="text-primary mt-1 mb-3">Unit Type : {{rc.unitTypeSizeConcat[0]}}</h3>
<table mat-table [dataSource]="datasource[i]" matSort class="mat-elevation-z8" matSortDisableClear>
<ng-container matColumnDef="unitRateType">
<th class="centered-sorted-header" mat-header-cell *matHeaderCellDef mat-sort-header>Unit Rate Filter</th>
<td mat-cell *matCellDef="let row; let i=index">{{row.list.unitRateType}}</td>
</ng-container>
<ng-container matColumnDef="rateChangeType">
<th class="centered-sorted-header" mat-header-cell *matHeaderCellDef mat-sort-header>Rate Change Type</th>
<td mat-cell *matCellDef="let row; let i=index">{{row.list.rateChangeType}}</td>
</ng-container>
<ng-container matColumnDef="effectiveDate">
<th class="centered-sorted-header" mat-header-cell *matHeaderCellDef mat-sort-header>Effective Date</th>
<td mat-cell *matCellDef="let row; let i=index">{{row.list.effectiveDate | date: 'MM-dd-yyyy'}}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
</div>
TS:
displayedColumns = [
'unitRateType',
'rateChangeType',
'effectiveDate'
];
@ViewChild(MatSort) sort: MatSort;
datasource: MatTableDataSource<any[]>[] = [];
ngOnInit(){
this.filteredSizeCode.forEach((size: any) => {
let data: any[] = size.list.map((x: any) => ({ ...size, list: x }));
console.log(data);
this.datasource.push(new MatTableDataSource(data));
});
this.datasource[0].sortingDataAccessor = (item: any, property) => {
console.log(item);
switch (property) {
case 'noticeDays':
return item.list.noticeDays;
case 'unitRateType':
return item.list.unitRateType;
case 'effectiveDate':
return item.list.effectiveDate;
default: return item[property];
}
}
this.datasource[0].sort = this.sort;
}
Assume that you have imported MatSortModule
.
You are getting the MatSort
directive from the view, you are only able to get it in the AfterViewInit
lifecycle.
Thus, move the logic for your custom sortingDataAccessor
and initialize MatSort
instance in MatTableDataSource
in the ngAfterViewInit
method.
ngAfterViewInit() {
this.datasource[0].sortingDataAccessor = (item: any, property) => {
console.log(item);
switch (property) {
case 'noticeDays':
return item.list.noticeDays;
case 'unitRateType':
return item.list.unitRateType;
case 'effectiveDate':
return item.list.effectiveDate;
default:
return item[property];
}
};
this.datasource[0].sort = this.sort;
}
For multiple MatTableDataSource
instances, you need to get all the MatSort
directives via @ViewChildren
and initialize the MatSort
instance by index.
import { QueryList, ViewChildren } from '@angular/core';
@ViewChildren(MatSort) sorts: QueryList<MatSort>;
ngAfterViewInit() {
for (let i = 0; i < this.datasource.length; i++) {
this.datasource[i].sortingDataAccessor = (item: any, property) => {
console.log(item);
switch (property) {
case 'noticeDays':
return item.list.noticeDays;
case 'unitRateType':
return item.list.unitRateType;
case 'effectiveDate':
return item.list.effectiveDate;
default:
return item[property];
}
};
this.datasource[i].sort = this.sorts.get(i)!;
}
}