Material UI DataGrid Sorting Dates Not Working as Expected

Viewed 683

I am using Material UI DataGrid and one of my columns contains dates. The Material UI documentation says to set the type to "date" in the column array, which I have done:

{
field: "submittedAt",
headerName: "Submitted",
minWidth: 150,
flex: 2,
type: "date",
headerClassName: "tableHeader",
cellClassName: "hoverPointer"
}

I am then converting my timestamp to MM/dd/yyyy format using Luxon

if (r.data().submittedAt) {
      const d = DateTime.fromMillis(r.data().submittedAt.toMillis());
      requestedDate = d.toFormat('MM/dd/yyyy')
    }

and then using requestedDate to set the value of the cell in the column. When I sort the data, the column is still sorting by a string comparator instead of by date:

enter image description here

I'm not sure what I'm doing wrong, and I can't seem to find much support in the documentation or in previous posts. I know I could set the date to yyyy/MM/dd so the string comparator works, but I don't want that format rendered for readability purposes. I also need the column to be dynamically sortable by the user, so server-side sorting won't help me out either. Thanks in advance for any help.

1 Answers

What I did:

  • in the data / the back end response, return an ISO timestamp that the DataGrid understands already (e.g. "2022-09-12T10:01:08+0200")
  • just change the way that timestamp is displayed to the user.

This way, the adjustments that you need to make are minimal (just the rendering code)

    const dateFormattingOptions: Intl.DateTimeFormatOptions = {
        year: 'numeric',
        month: '2-digit',
        day: '2-digit',
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit'
    };

    function renderDate(checkTimeAndDate: any) {
        if (!checkTimeAndDate) {
            return '';
        }
        return new Date(checkTimeAndDate).toLocaleDateString(
            'de-DE',
            dateFormattingOptions
        );
    }
    const columns: GridColDef[] = [
        // ...
        {
            field: 'myTimeAndDateField',
            headerName: 'My Time and Date',
            width: 250,
            type: 'dateTime',
            renderCell: (params: GridRenderCellParams<MyDataTypeWithADateField>) =>
                renderDate(params.row.myTimeAndDateField)
        },
        // ...
    ];
    return (<DataGrid
        rows={myData}
        columns={columns}
        // ...
    />);

Testing:

test('the data table renders timestamps, formatted for Germany', async () => {
    // ...
    render(<MyComponent />);

    expect(findDataFieldValue('myTimeAndDateField')).toBe('12.09.2022, 10:01:08');
});


function findDataFieldValue(dataField: string): string | null | undefined {
    // material UI makes this into a div - I need to get conceptual table cell instead
    const element: HTMLElement | null = document.querySelector<HTMLElement>(
        "div[role='cell'][data-field='" + dataField + "']"
    );
    return element?.textContent;
}

Test data:

export const testData: MyDataTypeWithADateField = {
    // ...
    myTimeAndDateField: '2022-09-12T10:01:08+0200',
    // ...
};
Related