Friday, 16 May 2025

Sorting in Angular Material Table

In the last post, we saw how to add paging in an Angular Material table. Now, we will see how to add sorting feature. Angular Material used here is version 19.

First we add MatSortModule in our AppModule:
. . .
import { MatSortModule } from '@angular/material/sort';

@NgModule({
  . . .
  
  imports: [
    . . .
    MatSortModule
  ],
  
  . . .
})

Then add matSort and mat-sort-header directives to the table on component page. Also we will add a function for matSortChange event:
<table mat-table [dataSource]="dataSource" matSort (matSortChange)="onSortChange($event)">

  <!-- First Name Column -->
  <ng-container matColumnDef="firstName">
    <th mat-header-cell *matHeaderCellDef mat-sort-header> First Name </th>
    <td mat-cell *matCellDef="let student"> {{student.firstName}} </td>
  </ng-container>

  <!-- Last Name Column -->
  <ng-container matColumnDef="lastName">
    <th mat-header-cell *matHeaderCellDef mat-sort-header> Last Name </th>
    <td mat-cell *matCellDef="let student"> {{student.lastName}} </td>
  </ng-container>

  . . .

  <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
  <tr mat-row *matRowDef="let row; columns: displayedColumns;" (click)="onRowClicked(row)"></tr>
</table>

Finally, modify the component class file:
. . .
import { MatTableDataSource } from '@angular/material/table';
import { MatPaginator } from '@angular/material/paginator';

// import MatSort and Sort directives
import { MatSort, Sort } from '@angular/material/sort';
. . .

export class SearchComponent implements OnInit {
  @ViewChild(MatPaginator) paginator!: MatPaginator;
  
  // add the MatSort component
  @ViewChild(MatSort) sort!: MatSort;
  . . .
  // make sure we use MatTableDataSource type for our data
  dataSource = new MatTableDataSource<Student>([]);
  totalRecords = 0;
  pageSize = 5;  
  
  ngOnInit(): void {
     . . .
     this.dataSource.paginator = this.paginator;       
	 
     // connect sorting to the data source
     this.dataSource.sort = this.sort;
  }
    
  findStudents() {

    // some logic to set or get sort field and direction 
    var sortField = 'studentId';
    var sortDirection = 'asc';
    if (this.sort?.active && this.sort?.direction) {
      sortField = this.sort.active;
      sortDirection = this.sort.direction;
    }

    var pageIndex = 0;
    var pageSize = 5;
    if (this.paginator?.pageIndex && this.paginator?.pageSize) {
      pageIndex = this.paginator.pageIndex;
      pageSize = this.paginator.pageSize;
    }
	
    this.studentService.findStudents(this.model, pageIndex, pageSize, sortField, sortDirection)
      .subscribe({
        next: (response: PaginatedResult<Student>) => {
          this.dataSource.data = response.data;
          this.totalRecords = response.totalRecords;
		  . . .
        }
      });
  }
  
  // respond to emitted events from 'matSortChange' when user is interacting with sort order
  onSortChange(sort: Sort) {
    this.paginator.pageIndex = 0;
    this.findStudents();
  }

  onPageChange(event: any) {
    this.findStudents();
  }
}