user8188349
user8188349

Reputation: 237

Material-UI DataGrid not sorting numeric column correctly

I am currently working on DataGrid Component from Material-UI. Data can be displayed, but the inbuilt sorting is not working as expected. When I try to sort ASC/DESC it is sorting based on the first digit of the number. Please look into the picture below:

Descending Order

I have tried the same with fake API in CodeSandbox. It is working fine but in my application the sorting is acting different.

Then I have tried to add sortModel (followed Material-UI Sorting docs) still it is acting the same. I haven't been able to find a solution in the docs.

const sortModel = [{ field: "canaryDeviceId", sort: "asc" }];

<div style={{ height: "90%", width: "100%" }}>
  <DataGrid sortModel={sortModel} rows={rows} columns={columns} />
</div>

Upvotes: 7

Views: 8425

Answers (4)

thclark
thclark

Reputation: 5461

You are suffering from the difference between alphabetic sort and natural sort.

The data grid allows you to implement your own sorting comparator, so you'd need to do that to get a natural sort algorithm.

In an alphabetic sort, you would get:

AA
AAA
AB

This is expected. Applied again to values with numbers, the following is correct (but not what you want):

A1
A11
A2

In a natural sort, the sort algorithm attempts to identify whole numbers within the text labels you're sorting, based on consecutive numberic digits being collapsed and treated as a number. You would get:

A1
A2
A11

Upvotes: -1

Sandeep Jain
Sandeep Jain

Reputation: 1261

        Type Number value coming from API server side and will display a different value with modification      
        
        { field: "controlTriggerLowerVal", headerName: "Lower Trigger", width: 150 ,type: "number",headerAlign: "left",
                              renderCell: (cellValues) => {
                                return  <> {cellValues.row.calculateLowerTrigger} </>;
                              },flex:1,align: 'left'
                              
    
    Another way to write custom sort , also handles null and space:
    
    nullSpaceHandlingSortComparator = (
        v1,
        v2,
        cellParams1,
        cellParams2
      ) => {
        const sortModel = cellParams1.api.getSortModel();
        const sortColumn = sortModel.find(
              (sm) => sm.field == cellParams1.field
        );
        if (sortColumn && sortColumn.sort == "desc") {
            if ((v1 == null && v2 == null) || (v1 == "" && v2 == "")) {
            return -1;
            }
            if ((v1 == null) || (v1 == "")) {
            return -1;
            }
            if ((v2 == null) || (v2 == "")) {
            return 1;
            }
          return v1 - v2; 
        }else{
    
          if ((v1 == null && v2 == null) || (v1 == "" && v2 == "")) {
              return 0;
          }
          if ((v1 == null) || (v1 == "")) {
              return 1;
          }
          if ((v2 == null) || (v2 == "")) {
              return -1;
          }
          return v1 - v2;  
        }
      };

 { field: "controlTriggerLowerVal", headerName: "Lower Trigger", width: 150 ,type: "number",headerAlign: "left",
                  renderCell: (cellValues) => {
                    return  <> {cellValues.row.calculateLowerTrigger} </>;
                  },flex:1,align: 'left',
                  sortComparator: this.nullSpaceHandlingSortComparator,
                  }

Upvotes: 0

dt777
dt777

Reputation: 21

sortComparator: (v1, v2) => parseInt(v1) - parseInt(v2),

work for me

Upvotes: 2

NearHuscarl
NearHuscarl

Reputation: 81400

I think DataGrid columns by default use string comparator, if you want to sort numeric column, try setting the type to 'number':

{
  field: "deviceID",
  headerName: "Canary DeviceID",
  type: "number",
},

Then I have tried to add sortModel (followed Material-UI Sorting docs) still it is acting the same.

sortModel only describes the sorting state of DataGrid so I doubt it will solve your problem.

Upvotes: 12

Related Questions