Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to sort MatTableDataSource programmatically?

Tags:

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.

like image 907
soupjake Avatar asked Mar 04 '19 11:03

soupjake


People also ask

What is sorting in angular material table?

Angular Material provides the MatSort directive as an easy way the include interactive sorting in the tables of your application. With the MatSort directive, the user can sort the data on different columns by clicking on the column header.

How do I disable mat sort?

We can disable the sorting of a table in 2 ways: We can add property matSortDisabled on matSort directive, or. Add disabled attribute on any single table header.


2 Answers

UPDATE

A bug was already reported to the Material team over at Github.com. It seems that this is currently not possible. Please use a manual approach or implement your own sorting header.


Try manually sorting the data of the datasource:

sortDataSource(id: string, start: string) {
    this.dataSource.sort.sort(<MatSortable>({ id: id, start: start }));
    this.dataSource.data.sort((a: any, b: any) => {
        if (a.createdDate < b.createdDate) {
            return -1;
        } else if (a.createdDate > b.createdDate) {
            return 1;
        } else {
            return 0;
        }
    });
}

You can easily make this more generic using the id and start parameters of your function.

like image 162
Julien Ambos Avatar answered Sep 30 '22 18:09

Julien Ambos


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>
like image 23
Jay Ahn Avatar answered Sep 30 '22 17:09

Jay Ahn