RyeGuy
RyeGuy

Reputation: 4483

Material UI select multiple dates with Calendar

I am implementing this Calendar component from Material UI and would like to be able to select multiple dates. When another date is selected it should remain highlighted. Below is what I have so far.

import React from 'react';
import Calendar from 'material-ui/DatePicker/Calendar';

class MultiCalendar extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            controlledDate: null,
        };
    }

    handleChange = (event, date) => {
        console.log('HERE');
        this.setState({
                controlledDate: date,
            });
         console.log(date);
         console.log(this.state.controlledDate);
    };

render() {
return (
    <Calendar 
        onChange={this.handleChange} 
        value={this.state.controlledDate} 
        className='calendar-test' id='calendar' 
        firstDayOfWeek={0} style={{ width: '500px' }}>
    </Calendar>

        );
      }
    }

export default MultiCalendar

(1) I can see here that the issue has been closed but I am not sure where to find the solution.

(2) The onChange event is not firing because those statements never appear in the console.

Any help with these issues would be wonderful. Thanks

Upvotes: 6

Views: 16866

Answers (1)

andres.ara
andres.ara

Reputation: 266

You can use StaticDatePicker and the property renderDay to allow many dates. The dates selected will be saved in values.

import * as React from "react";
import { styled } from "@mui/material/styles";
import TextField from "@mui/material/TextField";
import AdapterDateFns from "@mui/lab/AdapterDateFns";
import LocalizationProvider from "@mui/lab/LocalizationProvider";
import StaticDatePicker from "@mui/lab/StaticDatePicker";
import PickersDay from "@mui/lab/PickersDay";
import startOfDay from "date-fns/startOfDay";

const CustomPickersDay = styled(PickersDay, {
  shouldForwardProp: (prop) => prop !== "selected"
})(({ theme, selected }) => ({
  ...(selected && {
    backgroundColor: theme.palette.primary.main,
    color: theme.palette.common.white,
    "&:hover, &:focus": {
      backgroundColor: theme.palette.primary.dark
    },
    borderTopLeftRadius: "50%",
    borderBottomLeftRadius: "50%",
    borderTopRightRadius: "50%",
    borderBottomRightRadius: "50%"
  })
}));

export default function MultiDatePicker() {
  const [values, setValues] = React.useState([startOfDay(new Date())]);

  const findDate = (dates, date) => {
    const dateTime = date.getTime();
    return dates.find((item) => item.getTime() === dateTime);
  };

  const findIndexDate = (dates, date) => {
    const dateTime = date.getTime();
    return dates.findIndex((item) => item.getTime() === dateTime);
  };

  const renderPickerDay = (date, selectedDates, pickersDayProps) => {
    if (!values) {
      return <PickersDay {...pickersDayProps} />;
    }

    const selected = findDate(values, date);

    return (
      <CustomPickersDay
        {...pickersDayProps}
        disableMargin
        selected={selected}
      />
    );
  };

  return (
    <LocalizationProvider dateAdapter={AdapterDateFns}>
      <StaticDatePicker
        displayStaticWrapperAs="desktop"
        label="Week picker"
        value={values}
        onChange={(newValue) => {
          //copying the values array 
          const array = [...values];
          const date = startOfDay(newValue);
          const index = findIndexDate(array, date);
          if (index >= 0) {
            array.splice(index, 1);
          } else {
            array.push(date);
          }
          setValues(array);
        }}
        renderDay={renderPickerDay}
        renderInput={(params) => <TextField {...params} />}
        inputFormat="'Week of' MMM d"
      />
    </LocalizationProvider>
  );
}

The dependencies used in the example are:

  • @emotion/react latest (11.8.2)
  • @emotion/styled latest (11.8.1)
  • @mui/lab latest (5.0.0-alpha.72)
  • @mui/material latest (5.5.0)
  • date-fns latest (2.28.0)
  • react latest (17.0.2)
  • react-dom latest (17.0.2)

The view is.

enter image description here

Upvotes: 10

Related Questions