I'm working with an Angular Material table (mat-table) that has sorting enabled via matSort. Sorting works perfectly when I click on the column headers (mat-sort-header).
Now, I want to trigger the sort programmatically from a separate button. My goal is to sort the table by a specific column (e.g., 'itemNameFv') and have the UI update accordingly, including showing the correct sort arrow in the header.
I'm using Angular 9.1.13 and Angular Material 9.2.4.
What I've tried:
I have a MatSort instance in my component, accessed via @ViewChild:
@ViewChild("itemTableMatSort", { static: false }) matSort: MatSort;
And a button in my template that calls a function to perform the sort:
<button (click)="sortProgrammatically()">Sort by Name</button>
I have attempted several methods inside the sortProgrammatically() function, but none of them update the UI arrow, even if the data gets sorted.
Attempt 1: Directly setting active and direction and calling detectChanges
import { ChangeDetectorRef } from '@angular/core';
constructor(private cd: ChangeDetectorRef) {}
sortProgrammatically() {
this.matSort.active = 'itemNameFv';
this.matSort.direction = 'asc';
this.cd.detectChanges(); // This does not trigger the UI update for the arrow.
}
Result: The data doesn't sort, and the arrow doesn't appear.
Attempt 2: Emitting the sortChange event
This seems to be the recommended approach in many places.
sortProgrammatically() {
const sortState: Sort = { active: 'itemNameFv', direction: 'asc' };
// Manually update the MatSort state
this.matSort.active = sortState.active;
this.matSort.direction = sortState.direction;
// Emit the event to trigger the sort mechanism
this.matSort.sortChange.emit(sortState);
}
Result: This correctly triggers my (matSortChange) event handler, and my data sorting logic runs. The data in the table is sorted correctly. However, the sort indicator arrow on the itemNameFv column header does not appear.
Attempt 3: Using the sort() method of MatSort
I also tried using the official sort() method on the MatSort directive.
sortProgrammatically() {
this.matSort.sort({ id: 'itemNameFv', start: 'asc', disableClear: false });
}
Result: Same as attempt 2. The data sorts, but the UI arrow is not updated.
My (matSortChange) handler is complex:
It's worth noting that my sortChange() handler does more than just sort the local array. It re-calculates the data, handles pagination, and eventually updates the dataSource. At the end of my data processing, I've tried both this.matTable.renderRows() and this.orderList = [...this.orderList] to force a UI update, but neither of these makes the sort arrow appear when triggered programmatically.
Question:
What is the correct way to programmatically trigger MatSort in Angular Material (version 9) so that both the data sorting is applied and the mat-sort-header UI (the arrow) is updated to reflect the current sort state? Is there a step I'm missing to make the header aware of the programmatically initiated sort?