Reputation: 2834
The mat-sort icon is not showing when we sort the mat table by code. How can do the sort on clicking the button rather than clicking on the mat- header.
Upvotes: 4
Views: 7346
Reputation: 564
Initially I thought that the problem was simple but going ahead and reading the documentation and the source code, Angular material does not offer this functionality, it can be seen that is not working by subscribing to:
ngAfterViewInit() {
this.sort.sortChange.subscribe((x) => {
console.log(x);
});
}
The console response will be:
{active: "name", direction: "asc"}
So the id of the column will be triggered and the sort will be implemented on it, but the icon will not appaer.
I came with 2 implementations, your choice to choose witch one fit for you.
SOLUTION 1:
A quick fix but a little hugly will be to force the display of all the icon but will not have so much sense because we want to focus on a single column. To do that just past this in css:
::ng-deep .mat-sort-header-arrow {
opacity: 1 !important;
}
All the icons on header will be displayed only on header that have mat-sort-header attribute, and the icon change wil be triggered on the active column.
Stackblitz: https://stackblitz.com/edit/mattable-with-custom-sort-etzkcy
SOLUTION 2:
This is a bit hacky, so in order to trigger the animation on the icon we need to click on the header. So to that, i call a click event from component on mat-header-cell, but mat-header-cell is not clickable so i wrap the column name inside a div, in order to simulate the click
<mat-header-cell *matHeaderCellDef mat-sort-header>
<div #position>Position</div>
</mat-header-cell>
In the component we need to create a viewchildren for all the displayedColumns that we want to simulate the click:
@ViewChild('position') position:ElementRef;
@ViewChild('name') name:ElementRef;
In your method sortTest(val) i start to be a lot more hacky, so i switch the value of the string passed as parameter in val, to call the right click on the right header, bacause the name of the div and of the column are 1:1
switch(val) {
case "name": {
this.name.nativeElement.click()
this.name.nativeElement.click()
break;
}
case "position": {
this.position.nativeElement.click()
this.position.nativeElement.click()
break;
}
}
Why i call
this.position.nativeElement.click()
2 times? Bacause from what i understand
this.sort.active = val;
is counted as a click but without displaying the icon, so we will asc desc returning at the previously order, in order to avoid that i call it 2 time se the clicks are odd.
After all this hacky code i emit the sort
this.sort.active = val;
this.dataSource.sort = this.sort;
const sortState: Sort = {active: val, direction: this.sort.direction === 'asc' ? 'desc' : 'asc'};
this.sort.direction = sortState.direction;
this.sort.sortChange.emit(sortState);
I didn't figure out a better solution, even searching online, on the documentation, and on the sourcecode of angular material. I found a question like that without a single response.
Stackblitz of this solution: https://stackblitz.com/edit/mattable-with-custom-sort-emqkbs
Upvotes: 6