Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/angular/components/llms.txt

Use this file to discover all available pages before exploring further.

Directive to add sorting behavior and UI to table headers.

Import

import { MatSort, MatSortHeader } from '@angular/material/sort';
import { MatSortModule } from '@angular/material/sort';

Basic Usage

import { MatTableDataSource } from '@angular/material/table';
import { MatSort } from '@angular/material/sort';

export class TableComponent implements AfterViewInit {
  @ViewChild(MatSort) sort!: MatSort;
  
  displayedColumns = ['name', 'age', 'email'];
  dataSource = new MatTableDataSource([
    { name: 'John', age: 30, email: 'john@example.com' },
    { name: 'Jane', age: 25, email: 'jane@example.com' }
  ]);

  ngAfterViewInit() {
    this.dataSource.sort = this.sort;
  }
}
<table mat-table [dataSource]="dataSource" matSort>
  <ng-container matColumnDef="name">
    <th mat-header-cell *matHeaderCellDef mat-sort-header>Name</th>
    <td mat-cell *matCellDef="let element">{{element.name}}</td>
  </ng-container>

  <ng-container matColumnDef="age">
    <th mat-header-cell *matHeaderCellDef mat-sort-header>Age</th>
    <td mat-cell *matCellDef="let element">{{element.age}}</td>
  </ng-container>

  <ng-container matColumnDef="email">
    <th mat-header-cell *matHeaderCellDef mat-sort-header>Email</th>
    <td mat-cell *matCellDef="let element">{{element.email}}</td>
  </ng-container>

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

API Reference

MatSort

Selector: [matSort] Exported as: matSort

Properties

NameTypeDescription
@Input() matSortActivestringID of the currently sorted column
@Input() matSortStartSortDirectionStarting sort direction. Options: ‘asc’, ‘desc’. Default: ‘asc’
@Input() matSortDirectionSortDirectionCurrent sort direction
@Input() matSortDisableClearbooleanDisable clearing sort
@Input() matSortDisabledbooleanDisable sorting
@Output() matSortChangeEventEmitter<Sort>Event when sort state changes
initializedObservable<void>Emits when initialized

Methods

NameDescription
register(sortable: MatSortable): voidRegisters a sortable
deregister(sortable: MatSortable): voidUnregisters a sortable
sort(sortable: MatSortable): voidTriggers sort
getNextSortDirection(sortable: MatSortable): SortDirectionGets next direction

MatSortHeader

Selector: [mat-sort-header] Exported as: matSortHeader

Properties

NameTypeDescription
@Input() idstringID for this sort header
@Input() arrowPosition'before' | 'after'Arrow position. Default: ‘after’
@Input() startSortDirectionOverride default start direction
@Input() disabledbooleanDisable this header
@Input() disableClearbooleanDisable clearing for this header

Sort Direction

Sorting cycles through three states:
  1. Ascending ('asc')
  2. Descending ('desc')
  3. No sort ('') - unless disableClear is true

Examples

Custom Sort Direction

<!-- Start with descending -->
<table mat-table [dataSource]="dataSource" matSort matSortStart="desc">
  <ng-container matColumnDef="name">
    <th mat-header-cell *matHeaderCellDef mat-sort-header>Name</th>
    <td mat-cell *matCellDef="let element">{{element.name}}</td>
  </ng-container>
</table>

Disable Clear

<table mat-table [dataSource]="dataSource" matSort matSortDisableClear>
  <!-- Only cycles between asc and desc -->
  <ng-container matColumnDef="name">
    <th mat-header-cell *matHeaderCellDef mat-sort-header>Name</th>
    <td mat-cell *matCellDef="let element">{{element.name}}</td>
  </ng-container>
</table>

Disable Specific Column

<ng-container matColumnDef="email">
  <th mat-header-cell *matHeaderCellDef mat-sort-header [disabled]="true">
    Email (not sortable)
  </th>
  <td mat-cell *matCellDef="let element">{{element.email}}</td>
</ng-container>

Sort Change Event

export class TableComponent {
  onSortChange(sort: Sort) {
    console.log('Active column:', sort.active);
    console.log('Direction:', sort.direction);
  }
}
<table mat-table [dataSource]="dataSource" 
       matSort 
       (matSortChange)="onSortChange($event)">
  <!-- columns -->
</table>

Programmatic Sorting

export class TableComponent {
  @ViewChild(MatSort) sort!: MatSort;

  sortByName() {
    this.sort.active = 'name';
    this.sort.direction = 'asc';
    this.sort.sortChange.emit({
      active: 'name',
      direction: 'asc'
    });
  }
}

Custom Sort Logic

export class TableComponent {
  dataSource = new MatTableDataSource(data);

  ngAfterViewInit() {
    this.dataSource.sort = this.sort;
    
    // Custom sort accessor
    this.dataSource.sortingDataAccessor = (item, property) => {
      switch (property) {
        case 'name': return item.name.toLowerCase();
        case 'date': return new Date(item.date).getTime();
        default: return item[property];
      }
    };
  }
}

Arrow Position

<ng-container matColumnDef="name">
  <th mat-header-cell *matHeaderCellDef 
      mat-sort-header 
      arrowPosition="before">
    Name
  </th>
  <td mat-cell *matCellDef="let element">{{element.name}}</td>
</ng-container>

With Sticky Header

<div class="table-container">
  <table mat-table [dataSource]="dataSource" matSort>
    <!-- columns -->
    <tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
    <tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
  </table>
</div>

Custom Data Source

For custom data sources, handle sort manually:
export class TableComponent implements AfterViewInit {
  @ViewChild(MatSort) sort!: MatSort;
  dataSource = new CustomDataSource();

  ngAfterViewInit() {
    this.sort.sortChange.subscribe(() => {
      this.dataSource.sort(this.sort.active, this.sort.direction);
    });
  }
}

class CustomDataSource extends DataSource<any> {
  private data = [...]; // your data
  private dataSubject = new BehaviorSubject(this.data);

  connect(): Observable<any[]> {
    return this.dataSubject;
  }

  disconnect(): void {
    this.dataSubject.complete();
  }

  sort(column: string, direction: SortDirection) {
    const sorted = this.data.sort((a, b) => {
      const valueA = a[column];
      const valueB = b[column];
      return direction === 'asc' 
        ? (valueA < valueB ? -1 : 1)
        : (valueA > valueB ? -1 : 1);
    });
    this.dataSubject.next(sorted);
  }
}

Accessibility

  • Sortable headers have role="button"
  • Clicking or pressing Enter/Space triggers sort
  • Current sort state announced to screen readers
  • Sort arrows provide visual indication

Configuration

import { MAT_SORT_DEFAULT_OPTIONS } from '@angular/material/sort';

@NgModule({
  providers: [
    {
      provide: MAT_SORT_DEFAULT_OPTIONS,
      useValue: {
        disableClear: true,
        arrowPosition: 'before'
      }
    }
  ]
})
export class AppModule {}

Types

type SortDirection = 'asc' | 'desc' | '';

interface Sort {
  active: string;
  direction: SortDirection;
}

interface MatSortable {
  id: string;
  start: SortDirection;
  disableClear: boolean;
}