Sort Date Correctly with Material Angular Table
03 Jun 2019We will try sort a date field which is coming as string in MM/dd/YYYY.
Using Default Sort for String as date
Component code
import { Component, OnInit, ViewChild } from '@angular/core';
import {MatSort} from '@angular/material/sort';
import {MatTableDataSource} from '@angular/material/table';
const DATA = [
{birthDate: '07/03/1987', name: 'Jon Doe'},
{birthDate: '07/02/1987', name: 'Leo Yan'},
{birthDate: '05/18/1987', name: 'Jane Doe'},
{birthDate: '04/13/1990', name: 'Ron Doug'},
{birthDate: '08/23/1987', name: 'Kaven Paul'},
{birthDate: '08/03/1988', name: 'Sean Potson'},
];
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit{
name = 'Angular';
dataSource = new MatTableDataSource(DATA);
displayedColumns = ['birthDate', 'name'];
@ViewChild(MatSort, {static: true}) sort: MatSort;
ngOnInit(){
this.dataSource.sort = this.sort;
}
}
Template Code
<div class="mat-elevation-z8">
<table mat-table [dataSource]="dataSource" matSort>
<ng-container matColumnDef="birthDate">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Birth Date </th>
<td mat-cell *matCellDef="let element"> </td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
<td mat-cell *matCellDef="let element"> </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
</div>
Solution
We need to tell the mat to compare the Birth date as Date rather then string so the easy way is to convert string to date before sort, for that we’ll update the sortingDataAccessor
of MatTableDataSource
Update sortingDataAccessor
on ngOnInit()
ngOnInit(){
this.dataSource.sort = this.sort;
this.dataSource.sortingDataAccessor = (e, property) => {
switch (property)
{
case 'birthDate': return this.dateTransform(e.birthDate);
default: return e[property];
}
};
}
dateTransform
private dateTransform(val: string) {
console.log('val', val);
if (val) {
try {
const mval = new Date(val);
console.log('mval', mval);
return (+mval);
} catch (error) {
console.error(error);
console.log('error', error);
}
}
return 0;
}
Updated Component Code
import { Component, OnInit, ViewChild } from '@angular/core';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
const DATA = [
{ birthDate: '07/03/1987', name: 'Jon Doe' },
{ birthDate: '07/02/1987', name: 'Leo Yan' },
{ birthDate: '05/18/1987', name: 'Jane Doe' },
{ birthDate: '04/13/1990', name: 'Ron Doug' },
{ birthDate: '08/23/1987', name: 'Kaven Paul' },
{ birthDate: '08/03/1988', name: 'Sean Potson' },
];
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
name = 'Angular';
dataSource = new MatTableDataSource(DATA);
displayedColumns = ['birthDate', 'name'];
@ViewChild(MatSort, { static: true }) sort: MatSort;
ngOnInit() {
this.dataSource.sort = this.sort;
this.dataSource.sortingDataAccessor = (e, property) => {
switch (property) {
case 'birthDate': return this.dateTransform(e.birthDate);
default: return e[property];
}
};
}
private dateTransform(val: string) {
console.log('val', val);
if (val) {
try {
const mval = new Date(val);
console.log('mval', mval);
return (+mval);
} catch (error) {
console.error(error);
console.log('error', error);
}
}
return 0;
}
}
Get Code from @stackblitz.com https://stackblitz.com/edit/angular-l1dc65