I'm using AG-Grid, a data table package, in a React project of mine. This table holds a set of DateTime values. In order to filter the DateTime values in the table, I am using a slightly modified version of the example DateTime filter provided by the AG-Grid documentation, which uses the Flatpickr package.
The DateTime values in my table are in ISO string format. When I make a selection via the calendar and clock, the values in the filter inputs are not the same as what I am selecting on the calendar and they do not match the values in the table cells.
Here is a screenshot showing the difference between the calendar selection and the input:
And here is a screenshot of the results of the applied filters and how they do not match the inputs:
I've been stumped by this problem for a long time, so if anyone can help me figure out why the values in the inputs, calendar and filter results are not matching up, it would be a great help.
DataGrid.jsx (AG-Grid Docs for reference)
import React, { useState } from 'react';
import { AgGridColumn, AgGridReact } from 'ag-grid-react';
import DateTimePicker from './DateTimePicker';
import DATES from './data/DATES.json';
import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-alpine.css';
const DataGrid = () => {
const [rowData, setRowData] = useState(DATES);
const COLUMN_DEFINITION = [
{
field: 'dateTime',
headerName: 'Date Time',
filter: 'agDateColumnFilter',
filterParams: {
defaultOption: 'inRange',
// Filtering function for DateTime values:
comparator: function(filterLocalDate, cellValue) {
filterLocalDate = new Date(filterLocalDate);
cellValue = new Date(cellValue);
let filterBy = filterLocalDate.getTime();
let filterMe = cellValue.getTime();
if (filterBy === filterMe) {
return 0;
}
if (filterMe < filterBy) {
return -1;
}
if (filterMe > filterBy) {
return 1;
}
}
}
}
];
return (
<div className="ag-theme-alpine" style={{ height: 400, width: 600 }}>
<AgGridReact
columnDefs={COLUMN_DEFINITION}
rowData={rowData}
defaultColDef={{
sortable: true,
filter: true,
filterParams: {
buttons: ['apply', 'clear', 'reset', 'cancel']
}
}}
frameworkComponents={{
agDateInput: DateTimePicker
}}
/>
</div>
);
};
export default DataGrid;
DateTimePicker.jsx (Flatpickr Docs for reference):
import React, {
useEffect,
useState,
useRef,
forwardRef,
useImperativeHandle
} from 'react';
import flatpickr from 'flatpickr';
import 'flatpickr/dist/flatpickr.min.css';
export default forwardRef((props, ref) => {
const [date, setDate] = useState(null);
const [picker, setPicker] = useState(null);
const refFlatPickr = useRef();
const refInput = useRef();
const onDateChanged = selectedDates => {
const [selectedDate] = selectedDates;
setDate(selectedDate);
props.onDateChanged();
};
useEffect(() => {
setPicker(
flatpickr(refFlatPickr.current, {
onChange: onDateChanged,
dateFormat: 'Z',
wrap: true,
enableTime: true,
enableSeconds: true,
time_24hr: true
})
);
}, []);
useEffect(() => {
if (picker) {
picker.calendarContainer.classList.add('ag-custom-component-popup');
}
}, [picker]);
useEffect(() => {
if (picker) {
picker.setDate(date);
}
}, [date, picker]);
useImperativeHandle(ref, () => ({
getDate() {
return date;
},
setDate(date) {
setDate(date);
},
setInputPlaceholder(placeholder) {
if (refInput.current) {
refInput.current.setAttribute('placeholder', placeholder);
}
},
setInputAriaLabel(label) {
if (refInput.current) {
refInput.current.setAttribute('aria-label', label);
}
}
}));
return (
<div
className="ag-input-wrapper custom-date-filter"
role="presentation"
ref={refFlatPickr}
>
<input type="text" ref={refInput} data-input style={{ width: '100%' }} />
<a class="input-button" title="clear" data-clear>
<i class="fa fa-times" />
</a>
</div>
);
});
I made two changes to your example:
dateFormat: 'Z'
inside the date picker. This is causing the selected date and the date inside the input box of the date picker to have a different format.filterParams.comparator
I've removed the 'Z' appended to the end of the cellValue
string. It seems that when calling new Date(cellValue)
the date is not giving the correct hour value as the cellValue
string. So to fix this, I simply just removed 'Z'
:cellValue = new Date(cellValue.slice(0, -1));
See this implemented here: https://stackblitz.com/edit/react-6dwqvh?file=src%2FDataGrid.jsx