Reputation: 2632
Im using mat table with sorting, where I want to set default sorting on a certain column.
This works for plain attributes but not for nested ones.
Here is my table
<table mat-table [dataSource]="dataSource" multiTemplateDataRows
matSort matSortActive="break" matSortDirection="asc"
class="mat-elevation-z4 w-100">
My nested sorting
this.dataSource.sort = this.sort;
this.dataSource.sortingDataAccessor = (item, property) => {
switch(property) {
case 'break': return item.break.start;
default: return item[property];
}
};
Also this nested sorting is fine, when you are manually clicking on the header to sort, it does what I expect but on default it doesn't sort, only shows the sorting arrow.
That's how it looks like on page load:
Here is the corresponding stackblitz.
Upvotes: 3
Views: 6111
Reputation: 11
<ng-container matColumnDef="firstName">
<th mat-header-cell class="mat-header-sticky" id="firstName" *matHeaderCellDef mat-sort-header tabindex="0"
[attr.aria-label]="'First Name Tool Tip'" [matTooltip]="tooltipConfiguration['firstName']"
[matTooltipPosition]="'above'" [matTooltipClass]="'matTooltip-panel'">
First Name
</th>
<td mat-cell *matCellDef="let contact" class="align-center">
<span class="display-block overflow-ellipsis">
{{ contact.firstName }}
</span>
</td>
</ng-container>
Just use same matColumnDef="firstName"
and {{ contact.firstName }}
notice that the property .firstName
is matching with matColumnDef
ID. This is as per angular docs.
Upvotes: 1
Reputation: 913
Please try the below.
If you want to change the default direction, change it on the ngOnInit method call to this.sortItem
// app.component.ts
import { Component, ViewChild } from '@angular/core';
import { Sort, MatSort, MatPaginator } from '@angular/material';
import { interval } from 'rxjs';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
public displayedColumns: string[] = ['name', 'break',];
public sortedData: any;
constructor( ) { }
ngOnInit() {
setTimeout(() => {
this.sortItem({ active: 'break', direction: 'asc' });
}, 1000);
}
compare(a: number | string, b: number | string, isAsc: boolean) {
return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
}
sortItem(sort: Sort) {
const data = DATA_SOURCE.slice();
if (!sort.active || sort.direction === '') {
this.sortedData = data;
return;
}
this.sortedData = data.sort((a, b) => {
const isAsc = sort.direction === 'asc';
switch (sort.active) {
case 'break': return this.compare(a.breakTime.start, b.breakTime.start, isAsc);
default: return 0;
}
});
}
}
const DATA_SOURCE = [
{
name: 'Alice',
breakTime: {
start: '14-00',
end: '14-00'
},
},
{
name: 'Steve',
breakTime: {
start: '10-00',
end: '11-00'
},
},
{
name: 'Bob',
breakTime: {
start: '12-00',
end: '13-00'
},
},
];
// app.component.html
<table mat-table [dataSource]="sortedData" multiTemplateDataRows
matSort (matSortChange)="sortItem($event)"
class="mat-elevation-z4 w-100">
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let item"> {{item.name}} </td>
</ng-container>
<ng-container matColumnDef="break">
<th mat-header-cell *matHeaderCellDef mat-sort-header > Break </th>
<td mat-cell *matCellDef="let element">
{{element.breakTime.start}} - {{element.breakTime.end}}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let element; columns: displayedColumns;"
class="element-row"
[class.example-expanded-row]="expandedElement === element"
(click)="expandedElement = expandedElement === element ? null : element">
</tr>
</table>
Upvotes: 0
Reputation: 355
The initial sorting didn't work properly when i researched it in may.
In my case it was necessary to write my own setSortHeader
function that executes after getting data.
setSortHeader() {
this.sort.active = 'break';
this.sort.direction = 'desc';
this.sort.sortChange.emit({ active: this.sort.active, direction: this.sort.direction });
const sortHeader = this.sort.sortables.get('break');
if (sortHeader) sortHeader['_setAnimationTransitionState']({ toState: 'active' });
}
I'm not sure that this code still necessary but in my case that worked.
Upvotes: 2