1

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?

1 Answer 1

1

Based on this issue this was fixed sometime between Angular 9 and Angular 13. The issue description also contains a Stackblitz example that makes the arrow appear that you can use if you don't want to upgrade to a newer version:

    const sortValue: MatSortable = {
      id: 'name',
      start: 'asc',
      disableClear: undefined
    };
    this.sort.sort(sortValue);
    const sortHeader = this.sort.sortables.get('name');
    sortHeader['_setAnimationTransitionState']({toState: 'active'});
Sign up to request clarification or add additional context in comments.

1 Comment

It worked, thank you so much.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.