My mat-table is sorting by capitalized words, how can i fix this in angular?

Viewed 4085

I'm trying to use the mat-sort to order one mat-table in angular, the problem is when i order in ascendent/decrescent order, the algoritm order capitalized words first than uncapitalized. If i have one table with this names:

"Mark" "antony"

"Mark" shows first than antony.

This is the algoritm:

sortData(sort: Sort) {
    const data = this.descricoesProdutos.slice();
    if (!sort.active || sort.direction === '') {
      this.sortedData = data;
      return;
    }

    this.sortedData = data.sort((a, b) => {
      const isAsc = sort.direction === 'asc';
      switch (sort.active) {
        case 'nome': return this.compare(a.nome, b.nome, isAsc);
        case 'descricao': return this.compare(a.descricao, b.descricao, isAsc);
        default: return 0;
      }
    });
  }


  compare(a: number | string, b: number | string, isAsc: boolean) {
  return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
  }

My html:

<table matSort (matSortChange)="sortData($event)">
3 Answers

I saw a Github issue opened for this use case: https://github.com/angular/components/issues/9205

There is a very elegant answer provided by Dennis Du Krøger (LosD) and improved upon by Yakir Gottesman (YakirSmartag):

Within your ngOnInit(), add this and it will work for any case:

this.dataSource.sortingDataAccessor = (data: any, sortHeaderId: string): string => {
  if (typeof data[sortHeaderId] === 'string') {
    return data[sortHeaderId].toLocaleLowerCase();
  }

  return data[sortHeaderId];
};

Make the names upper(or lower)case first, then compare them. This difference then will disappear.

 return this.compare(a.nome.toUpperCase(), b.nome.toUpperCase(), isAsc);

Replace the sorting mechanism with your own, by using the sortingDataAccessor property of the data source.

ngAfterViewInit(): void {
    this.tableDataSource.sortingDataAccessor = this._sortingDataAccessor;
}

/**
 * @param item The table row data (object).
 * @param property The property to sort by.
 */
private _sortingDataAccessor = (item: MyItem, property: string): any => {
    switch (property) {
        case 'someCustomProperty':
            return ...;
        default:
            return item[property]?.toLowerCase() || 'Ω';
    }
}

It now automatically sorts all fields alphabetically, case insensitive. When a field needs custom sorting, it can be added to the switch-statement.


Note: By adding the omega-character, it indexes null/empty values higher than Z.

Regular behaviour:

  • empty
  • empty
  • Abc
  • Klm
  • Xyz

New behaviour:

  • Abc
  • Klm
  • Xyz
  • empty
  • empty
Related