0

Using this component i want to create a date picker that will be able to select multiple dates:

import React from "react";
import ReactDOM from "react-dom";
import "antd/dist/antd.css";
import "./index.css";
import { DatePicker, Space } from "antd";

let arr = [];

function onChange(date, dateString) {
  arr.push(...[date, ...arr]);
  console.log(arr);
}

ReactDOM.render(
  <Space direction="vertical">
    <DatePicker value={arr} onChange={onChange} open={true} showNow={false} />
  </Space>,
  document.getElementById("container")
);

demo: https://codesandbox.io/s/basic-antd494-forked-wvlbl?file=/index.js

But i get error: TypeError: date.clone is not a function
How to solve my issue and to get the expected result?

3
  • do you want to select multiple dates in one datepicker component? Commented Dec 29, 2020 at 16:15
  • @baymax, yes, i do. Could you help to change the component above? Commented Dec 29, 2020 at 16:17
  • Ant Design datepicker doesn't provide multiple dates atm, however there could be some workaround. I will post workaround soon. Commented Dec 29, 2020 at 16:25

1 Answer 1

1

Ant Design doens't provide multiple dates selection on Date Picker. You can use the components like Select, Calendar and Tag from Ant Design to customize Date Picker.

Here's a customized multiple selectable datepicker.

import React, { useCallback, useMemo } from "react";
import PropTypes from "prop-types";

import { Select, Calendar, Tag } from "antd";

function toValidArray(value) {
  const arr = Array.isArray(value) ? value : [value];

  return arr.filter(e => e != null && e != undefined); // must be ==
}

const MultipleDatePicker = React.forwardRef((props, ref) => {
  const { onChange = () => {}, value, format = "DD/MM" } = props;
  console.log(onChange);

  const arrValues = useMemo(() => toValidArray(value), [value]);

  const customRenderDate = useCallback(
    current => {
      if (arrValues.some(e => current.isSame(e))) {
        return <div className={"selectedDate"}>{current.format("DD")}</div>;
      }

      return <div>{current.format("DD")}</div>;
    },
    [arrValues]
  );

  const renderTag = useCallback(
    ({ value, onClose }) => {
      return (
        <Tag onClose={onClose} closable>
          {value?.format(format)}
        </Tag>
      );
    },
    [format]
  );

  const _onChange = useCallback(
    selected => {
      const index = arrValues.findIndex(e => e.isSame(selected));
      const temp = [...arrValues];

      if (index !== -1) {
        temp.splice(index, 1);
      } else {
        temp.push(selected);
      }

      onChange(temp);
    },
    [arrValues, onChange]
  );

  const onDeselect = useCallback(
    oldSelect => {
      const newVal = arrValues.filter(e => !e.isSame(oldSelect));
      onChange(newVal);
    },
    [arrValues, onChange]
  );

  return (
    <Select
      className="select"
      mode="tags"
      value={arrValues}
      dropdownMatchSelectWidth={false}
      onDeselect={onDeselect}
      tagRender={renderTag}
      dropdownRender={() => {
        return (
          <div className={"calendar"}>
            <Calendar
              fullscreen={false}
              dateFullCellRender={customRenderDate}
              onSelect={_onChange}
            />
          </div>
        );
      }}
    />
  );
});

MultipleDatePicker.propTypes = {
  onChange: PropTypes.func,
  value: PropTypes.oneOfType([
    PropTypes.array,
    PropTypes.string,
    PropTypes.object
  ]),
  format: PropTypes.string
};

export default MultipleDatePicker;

You can also try it here - https://codesandbox.io/s/vigilant-https-34li3

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.