AG-Grid 的日期时间过滤器 - 单击按钮时清除输入文本
Datetime filter for AG-Grid - Clear input text on button click
基于 this proposed solution in the AG-Grid Github issues, I am trying to implement a jQuery DateTime Picker as a filter in my React/AG_Grid 项目。
我目前设置了 table,这样我就可以通过单击按钮清除已应用于我的 table 的过滤器。期望的行为是单击“重置过滤器”按钮后,应清除过滤器 AND 过滤器输入中的文本。正如现在的设置,过滤器正在根据需要从 table 中清除,但是当我重新打开过滤器输入时,前一个过滤器的文本仍然存在。
我有一个 Code Sandbox set up here 和我当前设置的简化版本。
重建步骤:
- 打开事件时间戳列的过滤器
- 对事件时间戳列应用过滤器(2020/01/31 00:00 - 2020/06/31 00:00)
- 单击 table
顶部的 'Reset Filters'
- 打开事件时间戳列的过滤器
- 请注意,来自上一个过滤器的文本仍然填充输入
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,
minWidth: 100,
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!
当我试图自己解决这个问题时,我遇到了 这解释了为什么你应该 NOT 一起使用 React 和 jQuery。这是一个很好的建议,因为您可以在上面的示例中看到,除其他问题外,状态没有得到妥善管理。
进一步阅读 AG-Grid 文档后,custom date component section and this post on AG-Grid's blog, I was able to implement a solution that uses react-datetime-picker 作为自定义过滤器组件。然后你必须将它传递给 table 的 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
}}
...
/>
基于 this proposed solution in the AG-Grid Github issues, I am trying to implement a jQuery DateTime Picker as a filter in my React/AG_Grid 项目。
我目前设置了 table,这样我就可以通过单击按钮清除已应用于我的 table 的过滤器。期望的行为是单击“重置过滤器”按钮后,应清除过滤器 AND 过滤器输入中的文本。正如现在的设置,过滤器正在根据需要从 table 中清除,但是当我重新打开过滤器输入时,前一个过滤器的文本仍然存在。
我有一个 Code Sandbox set up here 和我当前设置的简化版本。
重建步骤:
- 打开事件时间戳列的过滤器
- 对事件时间戳列应用过滤器(2020/01/31 00:00 - 2020/06/31 00:00)
- 单击 table 顶部的 'Reset Filters'
- 打开事件时间戳列的过滤器
- 请注意,来自上一个过滤器的文本仍然填充输入
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,
minWidth: 100,
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!
当我试图自己解决这个问题时,我遇到了
进一步阅读 AG-Grid 文档后,custom date component section and this post on AG-Grid's blog, I was able to implement a solution that uses react-datetime-picker 作为自定义过滤器组件。然后你必须将它传递给 table 的 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
}}
...
/>