Reputation: 2069
this is my current code:
displayedColumns: string[] = ['id', 'dataYear', 'dataMonth', 'population', 'sources', 'created_at', 'updated_at', 'actions'];
@ViewChild(MatSort) sort: MatSort;
ngOnInit() {
this.sort.sort(<MatSortable>({id: 'updated_at', start: 'desc'}));
this.listData.sort = this.sort;
}
I can only make a default sorting for one column. What if I would like to do three column ( dataYear, dataMonth, updated_at) of sorting?
Below content is the HTML component:
<mat-table [dataSource]="listData" matSort>
<ng-container matColumnDef="id">
<mat-header-cell *matHeaderCellDef mat-sort-header class="hide"> Id. </mat-header-cell>
<mat-cell *matCellDef="let element" class="hide"> {{element.id}} </mat-cell>
</ng-container>
<ng-container matColumnDef="dataYear">
<mat-header-cell *matHeaderCellDef mat-sort-header> Year </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.dataYear}} </mat-cell>
</ng-container>
<ng-container matColumnDef="dataMonth">
<mat-header-cell *matHeaderCellDef mat-sort-header> Month </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.dataMonth}} </mat-cell>
</ng-container>
<ng-container matColumnDef="population">
<mat-header-cell *matHeaderCellDef mat-sort-header> Population </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.population}} </mat-cell>
</ng-container>
<ng-container matColumnDef="sources">
<mat-header-cell *matHeaderCellDef mat-sort-header> Sources </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.sources}} </mat-cell>
</ng-container>
<ng-container matColumnDef="created_at">
<mat-header-cell *matHeaderCellDef mat-sort-header> Created Time </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.created_at}} </mat-cell>
</ng-container>
<ng-container matColumnDef="updated_at">
<mat-header-cell *matHeaderCellDef mat-sort-header> Updated Time </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.updated_at}} </mat-cell>
</ng-container>
<ng-container matColumnDef="actions">
<mat-header-cell *matHeaderCellDef></mat-header-cell>
<mat-cell *matCellDef="let row">
<button mat-icon-button (click)="onEdit(row)"><mat-icon>launch</mat-icon></button>
<button mat-icon-button color="warn" (click)="onDelete(row.id)"><mat-icon>delete_outline</mat-icon></button>
</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
Upvotes: 3
Views: 10408
Reputation: 41
An Indirect way to do this is by using sortingDataAccessor function.
In your function, you can simply concatenate primary sort columns and then it will get sorted correctly.
For e.g. I want to sort due dates and then for same dates, by name.Here is how I achieved this:
this.dataSource.sortingDataAccessor = (item, property) => {
switch (property) {
case 'dueDate': return (item?.dueDate + item?.name);
case 'name': return item?.name;
}
Upvotes: 3
Reputation: 2069
Use the single sort for four times then it will come out what I want
The priority: update_at > dataYear > population > created_at
this.sort.sort(<MatSortable>({id: 'created_at', start: 'desc'}));
this.sort.sort(<MatSortable>({id: 'population', start: 'desc'}));
this.sort.sort(<MatSortable>({id: 'dataYear', start: 'desc'}));
this.sort.sort(<MatSortable>({id: 'updated_at', start: 'desc'}));
Upvotes: 2
Reputation: 6183
I don't think that is supported yet, see this Github issue here.
But you could just sort the data yourself, instead of relying on the Material data source to do it for you, which it can't as of now anyway (multiple field sorting that is).
Here is a quick stackblitz I threw together.
It doesn't use matSort
at all and just sorts the data of the data source itself via an array of Sort
objects:
export interface Sort {
id: string;
direction: 'asc' | 'desc';
}
multiSort: Sort[] = [
{ id: 'position', direction: 'desc' },
{ id: 'weight', direction: 'asc' },
{ id: 'name', direction: 'asc' }
];
And then the function that consumes the sort config:
public sort() {
if (!this.multiSort) {
return;
}
let sortedData: PeriodicElement[];
this.multiSort.forEach(sort => {
sortedData = this.dataSource.data
.sort((a, b) => {
if (sort.direction === 'asc') {
return a[sort.id] > b[sort.id] ? 1 : -1;
} else if (sort.direction === 'desc') {
return a[sort.id] > b[sort.id] ? -1: 1;
} else {
return 0;
}
});
});
this.dataSource.data = sortedData;
}
This might not be ideal but depending on your requirements a similar solution might get you to solve this issue.
Upvotes: 4