问题描述
基于 this proposed solution in the AG-Grid Github issues,我正在尝试在我的 jQuery DateTime Picker/React 项目中实现一个 AG_Grid 作为过滤器。
我目前已设置好我的表格,以便我可以通过单击按钮清除已应用于我的表格的过滤器。所需的行为是,一旦单击“重置过滤器”按钮,过滤器AND 过滤器输入内的文本应被清除。按照现在的设置,过滤器正在根据需要从表中清除,但是当我重新打开过滤器输入时,上一个过滤器中的文本仍然存在。
我有一个 Code Sandbox set up here,其中包含我当前设置的简化版本。
重新创建的步骤:
- 为事件时间戳列打开过滤器
- 将过滤器应用于事件时间戳列 (2020/01/31 00:00 - 2020/06/31 00:00)
- 点击表格顶部的“重置过滤器”
- 为事件时间戳列打开过滤器
- 请注意,来自上一个过滤器的文本仍会填充输入
const App = () => {
const [gridApi,setGridApi] = useState([]);
const [gridColumnApi,setGridColumnApi] = useState([]);
const [rowData,setRowData] = useState([]);
useEffect(() => {
const formattedDates = dataSet.map((data) => {
return {
id: data.id,eventTimestamp: new Date(data.eventTimestamp)
};
});
setRowData(formattedDates);
},[]);
// ***************************************************
// The Handle Click logic for the reset filters button:
// ***************************************************
const resetAppliedFilters = () => {
gridApi.setFilterModel(null);
CustomDateComponent.prototype.setDate(null);
};
const cols = [
{
field: "id",headerName: "ID",minWidth: 100,maxWidth: 150
},{
field: "eventTimestamp",headerName: "Event Timestamp",minWidth: 225,filter: "agDateColumnFilter",filterParams: {
defaultOption: "inRange",// ***************************************************
// Comparator function for datetime picker:
// ***************************************************
comparator: function (filterLocalDate,cellValue) {
filterLocalDate.setMilliseconds(0);
cellValue.setMilliseconds(0);
let filterBy = filterLocalDate.getTime();
let filterMe = cellValue.getTime();
if (filterBy === filterMe) {
return 0;
}
if (filterMe < filterBy) {
return -1;
}
if (filterMe > filterBy) {
return 1;
}
}
}
}
];
const onGridReady = (params) => {
setGridApi(params.api);
setGridColumnApi(params.columnApi);
// ***************************************************
// Table event listener:
// ***************************************************
params.api.addGlobalListener((type,event) => {
switch (type) {
case "filterChanged":
console.log(event);
return;
default:
return null;
}
});
};
return (
<div className="App">
<Button onClick={resetAppliedFilters} variant="outlined">
Reset Filters
</Button>
<hr />
<div
className={"ag-theme-balham"}
style={{ height: "86vh",width: "100%" }}
>
<AgGridReact
onGridReady={onGridReady}
rowData={rowData}
rowSelection="multiple"
defaultColDef={{
flex: 1,resizable: true,sortable: true,filter: true
}}
pagination
columnDefs={cols}
components={{
agDateInput: CustomDateComponent
}}
/>
</div>
</div>
);
};
// ***************************************************
// Custom datetime picker component:
// ***************************************************
function CustomDateComponent() {}
CustomDateComponent.prototype.init = function (params) {
this.params = params;
this.eGui = document.createElement("div");
this.eInput = document.createElement("input");
this.eGui.appendChild(this.eInput);
jQuery(this.eInput).datetimepicker({
mask: true,// '9999/19/39 29:59' - digit is the maximum possible for a cell
onChangeDateTime: this.onDateChanged.bind(this)
});
};
CustomDateComponent.prototype.onDateChanged = function (currentDateTime) {
this.date = currentDateTime;
this.params.onDateChanged();
};
CustomDateComponent.prototype.getGui = function () {
return this.eGui;
};
CustomDateComponent.prototype.getDate = function () {
return this.date;
};
CustomDateComponent.prototype.setDate = function (date) {
this.date = date;
};
CustomDateComponent.prototype.destroy = function () {
jQuery(this.eInput).datetimepicker("destroy");
};
export default App;
如果有人能帮助我或指出正确的方向,我们将不胜感激。 TIA!
解决方法
当我试图自己解决这个问题时,我发现 this Stack Overflow article 解释了为什么你应该不同时使用 React 和 jQuery。这是一个很好的建议,因为您可以在上面的示例中看到,状态没有得到适当的管理以及其他问题。
在进一步阅读 AG-Grid 文档的 custom date component 部分和 this post on AG-Grid's blog 后,我能够实现使用 react-datetime-picker 作为自定义过滤器组件的解决方案。然后,您必须将其传递给表的 frameworkComponents 属性。
DTPicker.jsx
import DateTimePicker from "react-datetime-picker";
export default forwardRef((props,ref) => {
const [selectedDate,setSelectedDate] = useState(null);
function handleDateChange(d) {
if (d) {
d = new Date(d);
setSelectedDate(d);
} else {
setSelectedDate(null);
}
}
// props.onDateChanged must be called after updating our component's internal state:
useEffect(props.onDateChanged,[selectedDate]);
// getDate and setDate are required by AG-Grid to sync ag-Grid's date
// filter value with that of our components:
useImperativeHandle(ref,() => {
return {
getDate: () => {
return selectedDate;
},setDate: d => {
handleDateChange(d);
}
};
});
return (
<>
<DateTimePicker
onChange={handleDateChange}
value={selectedDate}
maxDetail="second"
disableCalendar={true}
disableClock={true}
/>
</>
);
});
App.jsx
import DTPicker from './DTPicker'
// Add your custom filter logic in your column:
const cols = [
...,{
field: "eventTimestamp",headerName: "Event Timestamp",filter: "agDateColumnFilter",filterParams: {
defaultOption: "inRange",comparator: function(filterLocalDate,cellValue) {
let filterBy = filterLocalDate.getTime();
let filterMe = cellValue.getTime();
if (filterBy === filterMe) {
return 0;
}
if (filterMe < filterBy) {
return -1;
}
if (filterMe > filterBy) {
return 1;
}
}
}
},...
];
<AgGridReact
...
frameworkComponents={{
agDateInput: DTPicker
}}
...
/>