Description
Feature Description
MatTableDataSource<T>
already has a filterPredicate
property that allows you to pass a function with the signature (data: T, filter: string) => boolean
to implement a custom filtering algorithm. This makes it much easier to control the behavior of the table when passing a filter value to the data source.
The same thing is not possible when sorting: currently, the only way to control the behavior of a MatSort
on a MatTableDataSource
is to set its sortingDataAccessor
property. And this is extremely limited because it only allows to control what the sorting algorithm "sees" and not how it sorts the data.
Proposition:
Add a sortPredicate
analogous to MatTableDataSource.filterPredicate
to either MatTableDataSource
or MatSort
.
This property would accept a function with the signature (a: T, b: T, sort: Sort) => number
to mirror the signature of the comparison function passed to Array.sort
.
An alternative would be a signature like (sort: Sort) => (a: T, b: T) => number
which would return a comparison function derived the current sorting key/order.
Note that it would be better to be able to override the sort comparison function of only certain columns, in this case a possible solution would be to accept a function with the signature (sort: Sort) => ((a: T, b: T) => number) | undefined
and fallback to the default comparison function on undefined
.
This property would give a lot more control over the sorting algorithm to the user than what is currently possible.
Use Case
There is no easy way to customize the sorting algorithm, for ex: https://stackoverflow.com/q/55016642/10061195
This property would also make it easier to sort nested objects. Currently, this needs to either give a specific name to the column to sort, or to catch the data access using sortingDataAccessor
.
For example, a solution to the given SO question using the proposed property would be:
dataSource.sortPredicate = (sort: Sort) => {
if (sort.active === 'code') {
if (sort.direction === 'asc') {
return (a, b) => a.localeCompare(b, undefined, { numeric: true });
} else {
return (a, b) => b.localeCompare(a, undefined, { numeric: true });
}
}
};
or
// JS/TS does not support array as keys in object / Map
const compare = {
'code#asc': (a, b) => a.localeCompare(b, undefined, { numeric: true }),
'code#desc': (a, b) => b.localeCompare(a, undefined, { numeric: true }),
};
dataSource.sortPredicate = (sort: Sort) => compare[sort.active + '#' + sort.direction];