Skip to content

feat(MatTable) Add sortPredicate to MatTableDataSource or MatSort #24926

Open
@SadiinsoSnowfall

Description

@SadiinsoSnowfall

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];

Metadata

Metadata

Assignees

No one assigned

    Labels

    P4A relatively minor issue that is not relevant to core functionsarea: material/sortarea: material/tablefeatureThis issue represents a new feature or feature request rather than a bug or bug fix

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions