reactjsmaterial-uimui-x-date-picker

Open Dialog instead of Popper in desktop MUI X Date Picker v5


I want the MUI X v5 DatePicker (@mui/lab 5.0.0-alpha-51) to behave like the DesktopDatePicker (allowing to directly edit the date in the textbox). But when clicking on the calendar icon, I want to open the picker dialog, just like when clicking the MobileDatePicker.

I tried using the MobileDatePicker and added endAdornment to the InputProps to just get the calendar icon to draw. But this wasn't working.

Perhaps to put it more clearly: I want the DesktopDatePicker to open the Dialog of the MobileDatePicker when the user clicks on the calendar icon.

Is there a way to achieve this hybrid behavior?


Solution

  • If you have a look at MobileWrapper and DesktopWrapper definitions, you'll see that they use different components to display the picker (the former uses modal, the latter uses popover) and there is no way to swap it using the props provided by the picker component, but you also know where the internal modal comes from, so you can grab it:

    import PickersModalDialog from "@mui/lab/internal/pickers/PickersModalDialog";
    

    In this section, you can see that MUI exposes the StaticDatePicker which uses the internal Picker component that both the desktop and mobile pickers utilize, in case you want to build your own custom popup/modal, this is exactly what you want here, so grab this one too:

    import StaticDatePicker from '@mui/lab/StaticDatePicker';
    

    The next step is to integrate and make them work together, we have the DesktopDatePicker because you want to edit the TextField, the PickersModalDialog to display the StaticDatePicker in a modal. To do that you need to do the following things:

    Putting it together, we'll have something like below:

    const [value, setValue] = React.useState<Date | null>(() => new Date()); // (2)
    const [tempValue, setTempValue] = React.useState<Date | null>(null); // (3)
    const [open, setOpen] = React.useState(false); // (4)
    
    return (
      <>
        <DesktopDatePicker
          label="For desktop"
          value={value}
          open={false} // (1)
          onChange={(newValue) => setValue(newValue)}
          onOpen={() => {
            setTempValue(value);
            setOpen(true);
          }}
          renderInput={(params) => <TextField {...params} />}
        />
        <PickersModalDialog
          showTodayButton
          open={open}
          // (5)
          onAccept={() => {
            setValue(tempValue);
            setOpen(false);
          }}
          onSetToday={() => {
            setValue(new Date());
            setOpen(false);
          }}
          onDismiss={() => setOpen(false)}
          onClear={() => setOpen(false)}
        >
          <StaticDatePicker
            displayStaticWrapperAs="mobile"
            value={tempValue}
            onChange={(newValue) => setTempValue(newValue)}
            renderInput={(params) => <TextField {...params} />}
          />
        </PickersModalDialog>
      </>
    );
    

    Live Demo

    Codesandbox Demo