Components: Mat-table - sorting column containing both numbers and strings

Created on 15 Feb 2018  路  9Comments  路  Source: angular/components

Bug, feature request, or proposal:

Bug

What is the expected behavior?

When mixed values are in a column (by mixed I mean numbers and strings), numbers should appear before literals in ASC order, and after literals in DESC order

What is the current behavior?

Current order after sorting depends on initial order in the array - but it's not sorted in the way described above

What are the steps to reproduce?

Fill datatable with objects
[ {name: 'aaa'}, {name: '111'}, {name: 'ccc'} ]
configure datatable with sorter, column attached to name property and try sorting it. Notice that sorting is broken.

Sample bug reproduction can be found here:
https://stackblitz.com/edit/angular-material2-issue-t3va8d

What is the use-case or motivation for changing an existing behavior?

Presenting user entered content in table - where single column may contain both text and numbers

Which versions of Angular, Material, OS, TypeScript, browsers are affected?

To my knowlege - all. Having a quick glance into angular-material source it looks like purely material issue.

Most helpful comment

This appears to be due to the number coercion in MatTableDataSource's default sortingDataAccessor:

https://github.com/angular/material2/blob/d84612eac7a1f0e75948e4a9749e929ca387c6e0/src/lib/table/table-data-source.ts#L100-L104

I had never realized this before, but:

3333 > 'first' // false
3333 < 'first' // false

So a simple workaround/solution would be to define a sortingDataAccessor that doesn't coerce values to numbers:

ngAfterViewInit() {    
  this.dataSource.sort = this.sort;
  this.dataSource.sortingDataAccessor = (data, header) => data[header];
}

cc @andrewseguin

All 9 comments

This appears to be due to the number coercion in MatTableDataSource's default sortingDataAccessor:

https://github.com/angular/material2/blob/d84612eac7a1f0e75948e4a9749e929ca387c6e0/src/lib/table/table-data-source.ts#L100-L104

I had never realized this before, but:

3333 > 'first' // false
3333 < 'first' // false

So a simple workaround/solution would be to define a sortingDataAccessor that doesn't coerce values to numbers:

ngAfterViewInit() {    
  this.dataSource.sort = this.sort;
  this.dataSource.sortingDataAccessor = (data, header) => data[header];
}

cc @andrewseguin

I had never realized this before, but:

3333 > 'first' // false
3333 < 'first' // false

JS is awsome, isn't it? :)

Why is this part even needed?

_isNumberValue(value) ? Number(value) : value; 

Is there a work-around for this? Just curious about progress on this...

I was assigned a defect today for our app that is exactly this issue, all the columns sorted fine except for the one that uses a list of model numbers like this: ['319', '320', 'M83', 'M88', '31B', ...]

The 'sorted' order gets quite flaky. If I force each value to be a string by adding something like ':', the column sorts as expected. (If I add just a space or just a period, it doesn't.)

@willshowell mentioned a temporary workaround few posts above - You have to override default sortingDataAccessor in your DataSource.

Thanks @kaczmarekpawel -- somehow I missed the workaround even though I read that post... the workaround works great for me.

@kaczmarekpawel

Why is this part even needed?

_isNumberValue(value) ? Number(value) : value;

 1000  >  2  // true
'1000' > '2' // false

I think it'll be tricky to find a one-size-fits-all solution here, especially when the workaround is so simple. You could argue however that if the developer wanted to sort values numerically, they should use numbers in their array instead of relying on the data source to cast for them.

Certainly hard to find a solution that works for everyone, since naturally the MatTableDataSource has to have some opinion on this. Hopefully its simple enough to workaround with a custom accessor or by rolling your own data source

the work around fails for certain number & string combination
Example: https://stackblitz.com/edit/angular-material2-issue-hhey38

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

_This action has been performed automatically by a bot._

Was this page helpful?
0 / 5 - 0 ratings

Related issues

michaelb-01 picture michaelb-01  路  3Comments

savaryt picture savaryt  路  3Comments

MurhafSousli picture MurhafSousli  路  3Comments

julianobrasil picture julianobrasil  路  3Comments

RoxKilly picture RoxKilly  路  3Comments