Issue
I have a angular table but the date is not sorting correctly. The rest of the columns sort perfectly fine besides the date. I think its because the date is a nested object, I tried using the matSortChange() but nothing works.
I have created a demo here: DEMO
const ELEMENT_DATA: PeriodicElement[] = [
{position: 1,
name: 'A',
weight: 1.5079,
timeModel: {CreatedTime: "2020-04-30T15:38:11.186Z", LastModified: "2020-06-08T15:38:11.186Z"}
},
{position: 2,
name: 'B',
weight: 1.4079,
timeModel: {CreatedTime: "2021-03-30T15:38:11.186Z", LastModified: "2020-06-10T15:38:11.186Z"}
},
{position: 3,
name: 'C',
weight: 1.3079,
timeModel: {CreatedTime: "2020-01-30T15:38:11.186Z", LastModified: "2020-03-30T15:38:11.186Z"}
},
];
I did try to add a custom sort function to try to sort the dates but its not working correctly.
public changeSort(event: Event) {
if (event.active === 'date') {
this.dataSource.filteredData = this.dataSource.filteredData.sort(function(a, b) {
return new Date(a.timeModel.CreatedTime).getTime() - new Date(b.timeModel.CreatedTime).getTime();
});
}
}
HTML
<table mat-table [dataSource]="dataSource" (matSortChange)="changeSort($event)" matSort class="mat-elevation-z8">
<!-- Position Column -->
<ng-container matColumnDef="position">
<th mat-header-cell *matHeaderCellDef mat-sort-header> No. </th>
<td mat-cell *matCellDef="let element"> {{element.position}} </td>
</ng-container>
<!-- Name Column -->
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
<td mat-cell *matCellDef="let element"> {{element.name}} </td>
</ng-container>
<!-- Weight Column -->
<ng-container matColumnDef="weight">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Weight </th>
<td mat-cell *matCellDef="let element"> {{element.weight}} </td>
</ng-container>
<!-- Symbol Column -->
<ng-container matColumnDef="date">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Date </th>
<td mat-cell *matCellDef="let element"> {{element.timeModel.CreatedTime}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
}
Solution
Yes, the issue is because of it is an object. matColumnDef="weight"
describes the property to be taken into the sorting function. So from this object:
{
position: 1,
name: 'A',
weight: 1.5079,
timeModel: {CreatedTime: "2020-04-30T15:38:11.186Z", LastModified: "2020-06-08T15:38:11.186Z"}
}
weight
is taken. But matColumnDef="date"
results in just an undefined
- there is no property date
in your objects.
So if possible, change the dataSource objects and provide only the date it needs (as it seems you only use CreatedTime
anyways in your table).
You can also overwrite sortingDataAccessor
function of a MatDatSource, which originally looks like this atm:
sortingDataAccessor: ((data: T, sortHeaderId: string) => string|number) =
(data: T, sortHeaderId: string): string|number => {
const value = (data as {[key: string]: any})[sortHeaderId];
if (_isNumberValue(value)) {
const numberValue = Number(value);
return numberValue < MAX_SAFE_INTEGER ? numberValue : value;
}
return value;
}
You need to add a condition to look if the current sortHeaderId
value is a 'date'
. Then just tell it how to get the needed value of the object to be used in a sorting function:
this.dataSource.sortingDataAccessor = (data, sortHeaderId) => {
const value = (data as {[key: string]: any})[sortHeaderId];
const MAX_SAFE_INTEGER = 9007199254740991;
if (_isNumberValue(value)) {
const numberValue = Number(value);
return numberValue < MAX_SAFE_INTEGER ? numberValue : value;
}
if (sortHeaderId === 'date') {
return new Date(data.timeModel.CreatedTime)
}
return value;
}
p.s. you need to import MAX_SAFE_INTEGER
and _isNumberValue
from Angular if want to preserve that functionality.
Answered By - Julius Dzidzevičius
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.