2

I'm creating a table that should sort by file name and date I followed the Angular Material documentation for this purpose but is not working, it's not showing any errors in the compiler or the browser console, the table looks like this:

<mat-table [dataSource]="dataSource" matSort>
      <ng-container matColumnDef="File">
        <mat-header-cell *matHeaderCellDef mat-sort-header> File </mat-header-cell>
        <mat-cell  *matCellDef="let element" data-label="File"> {{element.fileName}} </mat-cell>
      </ng-container>

      <!-- Name Column -->
      <ng-container matColumnDef="Date">
        <mat-header-cell  *matHeaderCellDef mat-sort-header>Date </mat-header-cell>
        <mat-cell  *matCellDef="let element" data-label="Date"> {{element.date}} </mat-cell>
      </ng-container>
      <!-- Weight Column -->
      <ng-container matColumnDef="Extension">
        <mat-header-cell *matHeaderCellDef mat-sort-header>Extension</mat-header-cell>
        <mat-cell  *matCellDef="let element" data-label="Extension"> {{element.extension}} </mat-cell>
      </ng-container>



      <ng-container matColumnDef="View">
        <mat-header-cell *matHeaderCellDef> Actions </mat-header-cell>
        <mat-cell  *matCellDef="let element" data-label="View"> <a href="{{element.url}}" target="_blank" class="green-text"><i class="material-icons">visibility</i></a></mat-cell>
      </ng-container>

      <ng-container matColumnDef="Delete">
        <mat-header-cell *matHeaderCellDef> Delete </mat-header-cell>
        <mat-cell  *matCellDef="let element" data-label="Delete"> <a class="red-text"><i class="material-icons">delete_forever</i></a></mat-cell>
      </ng-container>
      <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
      <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
    </mat-table>

and this is my ts code

export class FilesComponent implements OnInit {
  displayedColumns: string[] = ['File', 'Extension', 'Date', 'View', 'Delete'];
  dataSource = new MatTableDataSource<Files>(ELEMENT_DATA);
  data = ELEMENT_DATA;
  selects: any;
  @ViewChild(MatPaginator, {static: true}) paginator: MatPaginator;
  @ViewChild(MatSort, {static: true}) sort: MatSort;
  constructor(private addFile: MatDialog) {
  }

  ngOnInit(): void {
    this.Materialize();
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
  }

  Materialize() {
    this.selects = document.querySelectorAll('select');
    M.FormSelect.init(this.selects);
  }

  changeFiles(value) {
    console.log('option:', value);
    switch (parseInt(value)) {
      case 1:
        this.dataSource = new MatTableDataSource<Files>(ELEMENT_DATA);
        break;
      case 2:
        this.dataSource = new MatTableDataSource<Files>(Charts);
        break;
      case 3:
        this.dataSource = new MatTableDataSource<Files>(Documents);
        break;
      default:
        this.dataSource = new MatTableDataSource<Files>(ELEMENT_DATA);
        break;
    }
    this.dataSource.sort = this.sort;
    this.dataSource.paginator = this.paginator;
  }
}

event the sort header it's applied and the styles (the arrows for the sort) appear in the table the data does not sort.

Dale K
  • 25,246
  • 15
  • 42
  • 71
Alan Alvarez
  • 37
  • 1
  • 4

3 Answers3

8

matColumnDef name and *matCellDef actual value name should be same

In component.html

Change

<ng-container matColumnDef="File"> <mat-header-cell *matHeaderCellDef mat-sort-header> File </mat-header-cell> <mat-cell *matCellDef="let element" data-label="File"> {{element.fileName}} </mat-cell></ng-container>

to

<ng-container matColumnDef="fileName"> <mat-header-cell *matHeaderCellDef mat-sort-header> File </mat-header-cell> <mat-cell *matCellDef="let element" data-label="File"> {{element.fileName}} </mat-cell> </ng-container>

In ts:

change

displayedColumns: string[] = ['File', 'Extension', 'Date', 'View', 'Delete'];

to

displayedColumns: string[] = ['fileName', 'Extension', 'Date', 'View', 'Delete'];
M A Salman
  • 3,666
  • 2
  • 12
  • 26
Goskula Jayachandra
  • 3,931
  • 2
  • 12
  • 22
  • worked for me!!! I used the same object property name in displayedColums array and matColumnDef and works it. Thanks. – Rafael Francisco Sep 22 '22 at 11:01
  • Tried sooo many things. This resolved it when nothing else did. Resolved after one hour, could have been many more. – Peter Jun 29 '23 at 06:16
1

@user12129132's answer will work for normal sorting ( You need to change the field values in the datasource to match the field values in the column definitions and also use the same in matColumn definition) but you have filename with numbers in it, it wont be sorted properly.For that purpose we can use sortingDataAccessor.

See the working version here - Stackblitz: https://stackblitz.com/edit/angular-g4svyj

ngAfterViewInit() {    
    this.dataSource.sort = this.sort;
    this.dataSource.sortingDataAccessor = (data, attribute) => {
        let formattedData=data[attribute]
        if(attribute=="fileName"){  
            formattedData=parseInt(formattedData.match(/(\d)*$/)[0]);
        }
        return formattedData;
    };
    this.dataSource.paginator = this.paginator; 
}
Pepe Alvarez
  • 1,218
  • 1
  • 9
  • 15
M A Salman
  • 3,666
  • 2
  • 12
  • 26
  • thanks for the moment i'm using only fake data but I'll have this in mind for when they give me the real data – Alan Alvarez Apr 02 '20 at 18:07
  • I only upvoted this because the afterviewInit life cycle is important to get the sorting -and also de paginator- working when you fetch the data through http for instance. – Pepe Alvarez Dec 06 '22 at 21:10
1

You need to add MatSortModule to the imports array in app.module.ts

Efi Gordon
  • 406
  • 1
  • 6
  • 9