0

基于AG-Grid Github 问题中提出的解决方案,我正在尝试在我的React / AG_Grid项目中实现一个jQuery DateTime Picker作为过滤器。

我目前设置了我的表格,以便我可以通过单击按钮清除已应用于我的表格的过滤器。期望的行为是,一旦单击重置过滤器按钮,过滤器过滤器输入内的文本应被清除。正如现在设置的那样,过滤器正在根据需要从表中清除,但是当我重新打开过滤器输入时,前一个过滤器中的文本仍然存在。


我在这里设置了一个代码沙箱,其中包含我当前设置的简化版本。

重建步骤:

  • 打开事件时间戳列的过滤器
  • 将过滤器应用于事件时间戳列 (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,
            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;

如果有人可以帮助或指出我正确的方向,将不胜感激。蒂亚!

4

1 回答 1

0

当我试图自己解决这个问题时,我偶然发现了这篇 Stack Overflow 文章,它解释了为什么不应该同时使用 React 和 jQuery。这是一个很好的建议,因为您可以在上面的示例中看到,在其他问题中没有正确管理状态。

在进一步阅读 AG-Grid 文档的自定义日期组件部分和AG-Grid 博客上的这篇文章后,我能够实现一个使用react-datetime-picker作为自定义过滤器组件的解决方案。然后,您必须将其传递给表的 frameworkComponents 道具。

Stack BLITZ 上的现场演示

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}
      />
    </>
  );
});

应用程序.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
    }}
    ...
/>
于 2021-03-16T19:19:29.117 回答