I have a normal Angular Material 2 DataTable with sort headers. All sort are headers work fine. Except for the one with an object as value. These doesn't sort at all.
For example:
<!-- Project Column - This should sort!--> <ng-container matColumnDef="project.name"> <mat-header-cell *matHeaderCellDef mat-sort-header> Project Name </mat-header-cell> <mat-cell *matCellDef="let element"> {{element.project.name}} </mat-cell> </ng-container>
note the element.project.name
Here's the displayColumn config:
displayedColumns = ['project.name', 'position', 'name', 'test', 'symbol'];
Changing 'project.name'
to 'project'
doesn't work nor "project['name']"
What am I missing? Is this even possible?
Here's a Stackblitz: Angular Material2 DataTable sort objects
Edit: Thanks for all your answers. I've already got it working with dynamic data. So I don't have to add a switch statement for every new nested property.
Here's my solution: (Creating a new DataSource which extends MatTableDataSource is not necessary)
export class NestedObjectsDataSource extends MatTableDataSource<MyObjectType> { sortingDataAccessor: ((data: WorkingHours, sortHeaderId: string) => string | number) = (data: WorkingHours, sortHeaderId: string): string | number => { let value = null; if (sortHeaderId.indexOf('.') !== -1) { const ids = sortHeaderId.split('.'); value = data[ids[0]][ids[1]]; } else { value = data[sortHeaderId]; } return _isNumberValue(value) ? Number(value) : value; } constructor() { super(); } }
It was hard to find documentation on this, but it is possible by using sortingDataAccessor
and a switch statement. For example:
@ViewChild(MatSort) sort: MatSort; ngOnInit() { this.dataSource = new MatTableDataSource(yourData); this.dataSource.sortingDataAccessor = (item, property) => { switch(property) { case 'project.name': return item.project.name; default: return item[property]; } }; this.dataSource.sort = sort; }
You can write a function in component to get deeply property from object. Then use it in dataSource.sortingDataAccessor
like below
getProperty = (obj, path) => ( path.split('.').reduce((o, p) => o && o[p], obj) ) ngOnInit() { this.dataSource = new MatTableDataSource(yourData); this.dataSource.sortingDataAccessor = (obj, property) => this.getProperty(obj, property); this.dataSource.sort = sort; } columnDefs = [ {name: 'project.name', title: 'Project Name'}, {name: 'position', title: 'Position'}, {name: 'name', title: 'Name'}, {name: 'test', title: 'Test'}, {name: 'symbol', title: 'Symbol'} ];
And in html
<ng-container *ngFor="let col of columnDefs" [matColumnDef]="col.name"> <mat-header-cell *matHeaderCellDef>{{ col.title }}</mat-header-cell> <mat-cell *matCellDef="let row"> {{ getProperty(row, col.name) }} </mat-cell> </ng-container>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With