Search code examples
reactjsmaterial-uicalendardatetimepicker

How can I disable a selected date on the Material UI calendar once the value is submited (booking system)


I integrated a simple calendar using Material UI Date & Time picker, which I would like to use inside my react app form to allow users to select a date and time (like a booking system) and submit it with their name and email. My idea was that once the user booked a date/time in the calendar. I Will be saved in an array. Then I'll check if the user selects the same date/time then I'll disable it in the calendar, so it will not be booked again. I tried to use ShouldDisableDate and I've done a lot of research, but I got stuck...

This is the documentation https://material-ui-pickers.dev/demo/datetime-picker

Ps: The booking component is separated from the form component. And the click button is only for debugging

What do you think?

import React, {useState } from "react";

import DateFnsUtils from '@date-io/date-fns';
import { DateTimePicker, MuiPickersUtilsProvider} from "@material-ui/pickers";

function Booking() {

  const [selectedDate, handleDateChange] = useState(new Date());
  const [calendarData, setCalendardata] = useState([]);
  console.log(calendarData);
  console.log(selectedDate);

  let stringfySelectedDate = JSON.stringify(selectedDate);

  const onSubmitDate = (e) => {
    e.preventdefault();
    
    // If the the array length is === to zero then add the first element
    if(calendarData.length === 0) {
      setCalendardata([...calendarData, stringfySelectedDate]);
      console.log("empty array");
    }

    if(calendarData.includes(stringfySelectedDate)) {
      console.log("already exist");
      return calendarData;
    } else {
      setCalendardata([...calendarData, JSON.stringify(selectedDate)]);
    }
  
  }

  
  return (
    <>
    <MuiPickersUtilsProvider utils={DateFnsUtils}>
      <DateTimePicker
        label="Book"
        inputVariant="outlined"
        value={selectedDate}
        onChange={handleDateChange}
        shouldDisableDate={}
        disablePast
        showTodayButton
        clearable
        id="calendar"
      />
    </MuiPickersUtilsProvider>
    <div className="col-12">
                          <div className="text-center">
                            <button
                              onClick={onSubmitDate}
                              className="nb butn light mt-30 full-width"
                            >
                              <span className="ls3 text-u">click</span>
                            </button>
                          </div>
                        </div>
    </>
  );
}

export default Booking;

Solution

  • You should use shouldDisableDate props. shouldDisableDate type is (date) => boolean.

    const [calendarData, setCalendardata] = useState([]);
    
    const onSubmitDate = (e) => {
       ///other actions
       setCalendardata([...calendarData, selectedDate.toDateString()]);
    }
    const checkDisableDate = (date) => {
       return calendarData.includes(date.toDateString());
    };
    return(
       <>
         //....
          <DateTimePicker
            ...otherProps
            shouldDisableDate={checkDisableDate}
          />
      </>
    )
    

    Update: Above Solution is only date. if for time, should use dropdown.

    const [selectedTime, setSelectedTime] = useState("0:00")
    
    const onSubmitDate = (e) => {
       ///other actions
        const date = selectedDate.toLocaleDateString();
        const dateTime = date + "*TZ" + selectedTime;
        setCalendardata([...calendarData, dateTime ]);
        setSelectedTime("");
    }
    const checkDisableDateTime = (time) => {
        var arr = calendarData.filter(x => x.split("*TZ")[0] === 
                                       selectedDate.toLocaleDateString());
        return arr.some(x => x.split("*TZ")[1] === time);
    } 
    return (
       <>
       //Other components    
            <Select
              value={selectedTime}
              onChange={(e) => setSelectedTime(e.target.value || "")}
              label="Time"             
            >
              <MenuItem value="">
              Select
              </MenuItem>
              {
                times.map((item,index) => {
                  return <MenuItem 
                           key={index} 
                           disabled={checkDisableDateTime(item)}  
                           value={item}>
                  {item}
                </MenuItem>
                })
              }
          </Select>
      </>
    
    )
    

    Edit Material demo (forked)