I’m presently trying to use Dash AG-Grid for a use-case in my org. One of those is to have filters through DateTime format (“YYYY-MM-DD HH:mm”). Since, the pre-configured agDateColumnFilter doesn’t allow inputs through the aforementioned format, I’m now working on a custom script for the same. A snippet of it goes like this (I’m obscuring certain aspects of it to maintain confidentiality): ABC.py: # Dynamically generate columnDefs columnDefs = [] for column in table_column_info: col_name = column["col_name"] data_type = column["data_type"] # Add the column definition column_def = { "field": col_name, "cellRenderer": "SpinnerCellRenderer", "sortable": True, "resizable": True, "headerClass": "abcd", "cellStyle": {"whiteSpace": "normal", "wordWrap": "break-word"}, "floatingFilter": True, } # Determine the filter type based on the data type if "datetime" in data_type.lower(): column_def["filter"] = "DateTimeFilter" elif data_type.lower() in ["string", "object"]: column_def["filter"] = "agTextColumnFilter" elif "int" or "float" or "double" in data_type.lower(): column_def["filter"] = "agNumberColumnFilter" # if filter_type: # column_def["filter"] = filter_type columnDefs.append(column_def) # Render the AgGrid component return dag.AgGrid( id="table-grid-view", columnDefs=columnDefs, defaultColDef={ "flex": 1, "minWidth": 150, "sortable": True, "resizable": True, }, rowModelType="infinite", # Use infinite row model dashGridOptions={ "rowBuffer": 0, "maxBlocksInCache": 2, "cacheBlockSize": 100, "cacheOverflowSize": 2, "maxConcurrentDatasourceRequests": 2, "infiniteInitialRowCount": 1, "pagination": True, "rowHeight": 30, }, ) dashAgGridComponentFunctions.js: (in assets folder) var dagcomponentfuncs = window.dashAgGridComponentFunctions = window.dashAgGridComponentFunctions || {}; const [useImperativeHandle, useState, useEffect, forwardRef] = [ React.useImperativeHandle, React.useState, React.useEffect, React.forwardRef, ]; dagcomponentfuncs.DateTimeFilter = forwardRef((props, ref) => { const [filterType, setFilterType] = useState("equals"); // Default filter type const [dateFrom, setDateFrom] = useState(""); // Start date const [dateTo, setDateTo] = useState(""); // End date (for "inRange") // Expose AG Grid Filter Lifecycle callbacks useImperativeHandle(ref, () => ({ doesFilterPass(params) { const cellValue = params.data[props.column.colId]; if (!cellValue) return false; const cellDate = new Date(cellValue); const fromDate = dateFrom ? new Date(dateFrom) : null; const toDate = dateTo ? new Date(dateTo) : null; switch (filterType) { case "equals": return fromDate && cellDate.getTime() === fromDate.getTime(); case "notEqual": return fromDate && cellDate.getTime() !== fromDate.getTime(); case "lessThan": return fromDate && cellDate < fromDate; case "greaterThan": return fromDate && cellDate > fromDate; case "inRange": return fromDate && toDate && cellDate >= fromDate && cellDate <= toDate; default: return true; } }, isFilterActive() { return !!dateFrom || !!dateTo; }, getModel() { if (!this.isFilterActive()) { return null; } return { [props.column.colId]: { // Use the column ID as the key type: filterType, dateFrom: dateFrom, dateTo: filterType === "inRange" ? dateTo : null, filterType: "date", }, }; }, setModel(model) { if (model && model[props.column.colId]) { const filterDetails = model[props.column.colId]; setFilterType(filterDetails.type || "equals"); setDateFrom(filterDetails.dateFrom || ""); setDateTo(filterDetails.dateTo || ""); } else { setFilterType("equals"); setDateFrom(""); setDateTo(""); } }, })); // Notify Ag-Grid when the filter changes useEffect(() => { props.filterChangedCallback(); }, [filterType, dateFrom, dateTo]); // Handle changes to the filter type function onFilterTypeChange(event) { setFilterType(event.target.value); } // Handle changes to the "dateFrom" input function onDateFromChange(event) { setDateFrom(event.target.value); } // Handle changes to the "dateTo" input (only for "inRange") function onDateToChange(event) { setDateTo(event.target.value); } return React.createElement( "div", { style: { display: "flex", flexDirection: "column", padding: "5px" } }, React.createElement( "select", { value: filterType, onChange: onFilterTypeChange, style: { marginBottom: "5px", padding: "5px", width: "100%" }, }, React.createElement("option", { value: "equals" }, "Equals"), React.createElement("option", { value: "notEqual" }, "Does not equal"), React.createElement("option", { value: "lessThan" }, "Before"), React.createElement("option", { value: "greaterThan" }, "After"), React.createElement("option", { value: "inRange" }, "Between") ), React.createElement("input", { type: "datetime-local", // HTML5 date-time picker value: dateFrom, onChange: onDateFromChange, style: { width: "100%", padding: "5px", marginBottom: "5px" }, }), filterType === "inRange" && React.createElement("input", { type: "datetime-local", // HTML5 date-time picker value: dateTo, onChange: onDateToChange, style: { width: "100%", padding: "5px" }, }) ); }); So now I’m getting the intended UI for DateTime filter. It is also getting triggered as soon as I start typing. However, I’m not able to get data from that input. For reference, I want my data to be parsed/captured like this for my filterModel : {'XXX_YY': {'dateFrom': '2025-04-02 00:00:00', 'dateTo': None, 'filterType': 'date', 'type': 'equals'}} where ‘XXX_YY’ is the name of column on which filter is being applied. Instead, at the moment, it just returns this: {}. What mistake might I be committing here? Or is there an easier alternative to my need - something like extending the functionality of “agDateColumnFilter” to have date-time input (instead of only date input) and the rest UI as is? I’m using dash_ag_grid==31.2.0, plotly==5.23.0 & Python 3.12.4 and operating in Chrome browser. Continue reading...