'How to sort MatTableDataSource programmatically?

I'm trying to sort the MatTableDataSource programmatically so that I can sort the data via the use of a button rather than by the table column header when viewing the data in a specific mobile layout. However, I'm having trouble doing so.

I've followed this post's advice on how to do it but the data sort is not being reflected. The mobile layout design for using the same data as the table:

<mat-card matSort *ngFor="let item of dataSource.filteredData">

The function I'm using to try and sort the data is:

sortDataSource(id: string, start: string){
  this.dataSource.sort.sort(<MatSortable>({id: id, start: start}));
}

which is called from tapping onto a button within a mat-menu e.g.

<mat-menu #sortMenu="matMenu" yPosition="below" [overlapTrigger]="false">
            <button mat-menu-item (click)="sortDataSource('createdDate', 'asc')"><span>Creation Date</span><mat-icon>arrow_upward</mat-icon></button>

Any help on this would be greatly appreciated!

Link to StackBlitz.

Edit: Adding where I'm assigning the data to the table's dataSource which comes from an Observable array:

this.data$.subscribe(data => {
      this.dataSource.data = data;
      this.dataSource.paginator = this.paginator;
      this.dataSource.sort = this.sort;
}

Edit 2: Removed error image as fixed by add "matSort" to the the mat-card using *ngFor for creating the mobile layout version of the mat-table.



Solution 1:[1]

When you reassign dataSource.sort with matSort, the template gets notified on the change and represent the changes.

component.ts

@ViewChild(MatSort, { static: false }) matSort: MatSort;

  orderData(id: string, start?: 'asc' | 'desc') {
    const matSort = this.dataSource.sort;
    const toState = 'active';
    const disableClear = false;

    matSort.sort({ id: null, start, disableClear });
    matSort.sort({ id, start, disableClear });

    this.dataSource.sort = this.matSort;
  }

component.html

<button mat-raised-button
   (click)="orderData('nameOfColumn', 'asc')">ASC</button>
<button mat-raised-button
   (click)="orderData('nameOfColumn', 'desc')">DESC</button>

Solution 2:[2]

Might be the shortest sort manually function for Material Table

Here is my short solution combined with JavaScript:

sortDataSource(idVal: string, startVal?: string): void {
    this.dataSource.data.sort(
        (a, b) => {
            return startVal === 'asc' ? a[idVal] - b[idVal] : (startVal === 'desc' ? b[idVal] - a[idVal] : a[idVal] - b[idVal]);
        }
    );
}

Solution 3:[3]

https://stackblitz.com/edit/angular-mat-sort-default-ytu6ch

check this out!

instead of manually sorting with the array.sort we can make use of the @ViewChild(MatSort) sort!: MatSort; and import { MatSort, Sort } from '@angular/material/sort';

to sort based on condition.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Shalem
Solution 2 AndyNope
Solution 3 sudhagar murugesan