I am trying to get the mat-table
sorting to work locally, and while I can get the data to show up as expected, clicking on the header row does not do the sortin
Actually matColumnDef name(i.e column name) and your Class/Interface property name should be equal to make it work.
Sometimes we can't change our Class/Interface property name, in that case, we can implement custom sorting as below.
let say your columns as ['id', 'name'] and
your class/interface as ['userId', 'name']
if we perform sorting on the 'id' column it won't work. Try with the custom sorting
this.dataSource.sortingDataAccessor = (item,property)=>{
// where item is your class/interface data
// where property is your column name
switch(property){
case 'id' : return item.userId
default: return item[property];
}
}
I found multiple answers to this question, but implementing them individually did not give me any results. So I tried to merge answers and it worked.
Firstly, I added ViewChild sort inside NgAfterViewInit interface. (It was initially inside a function that was called through NgOnInit
ngAfterViewInit(){
this.tableData.sort = this.sort;
}
For the second step i changed the *ngIf inside a container to [hidden]. I do get an error that says that the value is not loaded. But it is not a major one to be concerned about till now.
before
<div class="mat-elevation-z0 container-fluid" *ngIf={some boolean resultant condition}>
after
<div class="mat-elevation-z0 container-fluid" [hidden] = {negation of your boolean expression}>
psst.. You can also consider adding a loading spinner while your table is being loaded through mat-footer to above the above bs.
<ng-container matColumnDef="loading">
<mat-footer-cell *matFooterCellDef colspan=6>
<div class="uploader-status">
<mat-spinner strokeWidth="25" [diameter]="100" title="Server Starting" ></mat-spinner>
</div>
</mat-footer-cell>
</ng-container>
<mat-footer-row *matFooterRowDef="['loading']" [ngStyle]="{'display': (this.candidateService.candidateRecords!=null) ? 'none':'block'}"></mat-footer-row>
Adding sort within timeout block works for me,
dataSource = new MatTableDataSource(this.articleService.getAllArticles());
setTimeout(() => {
this.tableDataSource.sort = this.sort;
this.tableDataSource.paginator = this.paginator;
});
If you don't want to use lifecykle hooks.
I found this old blog which helped me get it to work: https://www.jeffryhouser.com/index.cfm/2018/10/23/Five-Reasons-My-ngMaterial-Table-wont-sort
MatSortModule
matSort
headerMatTableDataSource
<table mat-table [dataSource]="this.products" matSort>
) but I should have used the datasource object I initialized in the code (<table mat-table [dataSource]="this.dataSource" matSort>
). The datasource is initialized like dataSource = new MatTableDataSource(this.products)
ngOnInit
/ngAfterViewInit
MatTableDataSource
My solution was to fix several things (basically merging most of the solutions in this page).
Things to check:
BrowserModule, MatTableModule, MatSortModule
Modules should be imported in the root modules file.MatTableDatasource
class and pass your data array in it as a parameter*ngIf=....
directive. Use other conditional operations instead (still don't understand why).If your table is inside an *ngIf and you think it has something to do with it not sorting your table, then specifying your own sortingDataAccessor
function might solve the issue as it did for me. I have my table inside couple of *ngIfs and taking it out of those *ngIfs did not make sense:
`ngAfterViewInit(): void {
this.matchesDataSource.sort = this.sort;
this.matchesDataSource.sortingDataAccessor = previewMatchSortingFn;
}`
`export function previewMatchSortingFn(item: Match, header: string): string | number {
switch (header) {
case 'home':
return item.homeTeam.name;
case 'away':
return item.awayTeam.name;
case 'date':
if (item.dateTime) {
// this will return the number representation of the date
return item.dateTime.valueOf();
}
return;
default:
break;
}
}`