How can I clear Material UI DatePicker input?
Asked Answered
D

9

20

I would like to add a 'clear' button to a DatePicker from @mui/lab (5.0.0-alpha.55).

What I am attempting:

  • Store a date field in state, passed as the value prop to DatePicker
  • Change the date to null when desired to 'clear' the value & input

The behaviour I observe:

  • If the date is valid, it works as expected, and the input is cleared
  • If the date is not valid, the error is cleared, but the invalid date still stays in the input.

The rudimentary version I have attempted which shows the behaviour above can be seen here.

If you input a partial date, then click clear, you can observe that the input does not get cleared.

I would prefer to avoid a solution that involves changing the key, as that brings other issues, such as not respecting an external source changing the date to null, and needing additional hacks to respect the label transition when clearing the input.

Dorcy answered 19/11, 2021 at 21:29 Comment(1)
DatePicker now supports clear action: ==> mui.com/x/react-date-pickers/custom-components/#action-bar <==Ricercare
M
6

My theory is that internally, DatePicker only updates the input value if it's different with the last valid value. Below is how the bug can occur:

  • You clear the DatePicker when there is a valid value (like the initial Date), the state is reset successfully at first (value=null, inputValue='')
  • You enter some invalid date. The state is now (value=Invalid Date, inputValue='invalid Text')
  • Because the current value is invalid, it does not count and the DatePicker references the last valid value instead which is null, then decide that the current value doesn't change and skip dispatching the new input value (value=null, inputValue='invalid Text').

I'd classify this as a bug from MUI, you can create an issue on github if you want it to be fixed. In the meanwhile, you can fix the bug by applying this patch using patch-package:

  • Install patch-package: npm i patch-package
  • Add postinstall script in the package.json
"scripts": {
  "postinstall": "patch-package"
}
  • Open the buggy file at node_modules\@mui\lab\internal\pickers\hooks\useMaskedInput.js and change it based on this commit.
  • Run npx patch-package @mui/lab to create the patch that will be applied every time after you ran npm i @mui/lab again.
  • Restart your dev server.
Malachi answered 20/11, 2021 at 12:47 Comment(3)
Thank you for the feedback. Unfortunately that solution doesn't work properly. It causes an issue with the follow-up onChange event where the cursor stays at the start of the input after inputting the first character. I'll file a github issue as it seems like this needs to be fixed internally to fully behave properly. Edit: I found an existing github issue describing the problem here: github.com/mui-org/material-ui/issues/29001Dorcy
@JoshFraser see my updated answer. The code from the issue you linked above should fix the problem.Malachi
Thanks @NearHuscarl. Your updated answer worked well, but I had to also change the file at node_modules\@mui\lab\node\internal\pickers\hooks\useMaskedInput.js in addition to the location you provided, in order for my jest tests to get the changes too.Dorcy
D
20

For @mui/x-date-pickers v5 you could do:

<DatePicker
  componentsProps={{
    actionBar: {
      actions: ['clear'],
    },
  }}
  onAccept={(newDate) => {
    console.log(newDate);
  }}
/>

and see if newDate is null.

Important updates:

  1. For @mui/x-date-pickers v6 please see the other comment
  2. By default mobile and desktop don't have the same behavior, and just specifying clear will make the user stuck on mobile. Consider having ['clear', 'accept'] for mobile and ['clear'] for desktop, or simpler, merge the behavior by using the property closeOnSelect={true|false} to force on both platforms.
Dolomite answered 23/1, 2023 at 17:55 Comment(1)
componentsProps is deprecated, can now use slotProps insteadWatteau
T
11

As an extension to Thomas' answer, you can pass clear to the slotProps if you are using MUI 5:

<MobileDatePicker
  ...
  slotProps={{
    actionBar: {
      actions: ['clear']
    }
  }}
  ...
/>

References:

Tracee answered 22/3, 2023 at 3:55 Comment(0)
C
9

@mui/x-date-pickers package version v6.16.0 now has this feature built in:

import { DatePicker } from '@mui/x-date-pickers/DatePicker';

<DatePicker
   slotProps={{ field: { clearable: true } }}
/>

source: https://github.com/mui/mui-x/releases/tag/v6.16.0

Cultigen answered 3/10, 2023 at 12:55 Comment(0)
M
6

My theory is that internally, DatePicker only updates the input value if it's different with the last valid value. Below is how the bug can occur:

  • You clear the DatePicker when there is a valid value (like the initial Date), the state is reset successfully at first (value=null, inputValue='')
  • You enter some invalid date. The state is now (value=Invalid Date, inputValue='invalid Text')
  • Because the current value is invalid, it does not count and the DatePicker references the last valid value instead which is null, then decide that the current value doesn't change and skip dispatching the new input value (value=null, inputValue='invalid Text').

I'd classify this as a bug from MUI, you can create an issue on github if you want it to be fixed. In the meanwhile, you can fix the bug by applying this patch using patch-package:

  • Install patch-package: npm i patch-package
  • Add postinstall script in the package.json
"scripts": {
  "postinstall": "patch-package"
}
  • Open the buggy file at node_modules\@mui\lab\internal\pickers\hooks\useMaskedInput.js and change it based on this commit.
  • Run npx patch-package @mui/lab to create the patch that will be applied every time after you ran npm i @mui/lab again.
  • Restart your dev server.
Malachi answered 20/11, 2021 at 12:47 Comment(3)
Thank you for the feedback. Unfortunately that solution doesn't work properly. It causes an issue with the follow-up onChange event where the cursor stays at the start of the input after inputting the first character. I'll file a github issue as it seems like this needs to be fixed internally to fully behave properly. Edit: I found an existing github issue describing the problem here: github.com/mui-org/material-ui/issues/29001Dorcy
@JoshFraser see my updated answer. The code from the issue you linked above should fix the problem.Malachi
Thanks @NearHuscarl. Your updated answer worked well, but I had to also change the file at node_modules\@mui\lab\node\internal\pickers\hooks\useMaskedInput.js in addition to the location you provided, in order for my jest tests to get the changes too.Dorcy
C
4

how about this custom component?.

const DatePickerClear = (props) => {
  const { onClear } = props;
  return (
    <LocalizationProvider dateAdapter={AdapterDateFns}>
      <DatePicker
        {...props}
        renderInput={(params) => (
          <div style={{ position: "relative", display: "inline-block" }} >
            <TextField {...params} />
            {props.value &&
              <IconButton style={{ position: "absolute", top: ".5rem", margin: "auto", right: "2rem" }} onClick={() => onClear()}>
                <ClearIcon />
              </IconButton>
            }
          </div>
        )
        }
      /></LocalizationProvider >
  )
}

export default DatePickerClear

I give you too a github basic project in react.

enter image description here

https://github.com/HastaCs/MUI_DatePicker_ClearButton

Carcinomatosis answered 8/12, 2022 at 20:49 Comment(1)
This works pretty neat, except when picking a date, the date-selector pop-up flickers in the top-left corner for a second before closing itself. Also, you need to use slots prop instead of renderInput for newer versions of MUI.Than
S
4

I've tried it many ways but finally what worked for me is to change key while clearing from custom clear button, looks little dirty but that only what I was possibly able to

const [pickerKey, setPickerKey] = useState("pickerKey");
const handleClear = useCallback(() => {
    onChange("");
    setPickerKey(Math.random().toString());
}, [onChange]);



<DatePicker
   ...
   key={pickerKey}
   ...
/>
Styx answered 19/6, 2023 at 17:14 Comment(1)
this is the only thing that worked for me.Memberg
H
0
<DatePicker
  slotProps={{
    actionBar: {
      actions: ['clear'],
    },
  }}
/>

The other solution to clear an invalid date is to pass a state to your date picker to maintain the value and reset it to null. Below is the code snippet:

<DatePicker
  label={props?.label}
  slotProps={{
    actionBar: {
      actions: [props?.clearable?.toString()],
    },
    inputAdornment: {
      onClick: () => {
        setIsOpen(true);
      },
    },
    toolbar: {
      toolbarFormat: props?.disableToolbar,
    },
    ...(!props.disablePopper && {
      popper: { disablePortal: true, open: isOpen },
    }),
    textField: {
      inputProps: {
        onFocus: (e) => {
          setIsOpen(false);
          setDisplay(false);
        },
        style: props?.InputProps?.style,
        onBlur: (e) => {
          props?.onBlur ? props.onBlur(e) : handleDateChange(e);
        },
        onKeyDown: (e) => {
          props?.isEXR
            ? props?.onKeyDown && props.onKeyDown(e)
            : handleKeyDown(e);
        },
      },
      placeholder: props?.placeholder ? props?.placeholder : "Enter Date",
    },
  }}
  slots={{
    ...props,
    ...props?.dateProps,
  }}
  autoFocus={!display}
  onChange={props?.isEXR ? props.onChange : () => undefined}
  onAccept={handleDateChange}
  onClose={() => setIsOpen(false)}
  minDate={props.minDate ? dayjs(props.minDate) : null}
  maxDate={props.maxDate ? dayjs(props.maxDate) : null}
  sx={
    props.style || {
      width: props?.style?.width || "100%",
      borderRadius: 4,
      fontSize: props?.style?.fontSize || "12px",
    }
  }
  format={
    display
      ? props?.format || DIPLAY_DATE_FORMAT_DAYJS
      : INPUT_DATE_FORMAT_DAYJS
  }
  disabled={props?.isEXR && props?.disabled}
  readOnly={props.disabled}
  value={props.value ? dayjs(props.value) : null}
  onError={(e) => {
    return props.onError ? props.onError(e) : "Date Not Valid";
  }}
/>
Haematoma answered 23/7, 2024 at 6:6 Comment(0)
F
-1

MUI DatePicker has a clearable property. When set to true, it shows a clear button. You can change the text of the clear button using the clearText property. I would point out however, that it does not trigger an onChange event, nor is there an onClear event (at the time of writing this post). So when I am using it, its not possible to change the state that way. However the onAccept event is fired, and if you pass the value parameter, it will be null.

<MobileDatePicker
  open
  clearable
  label="some label"
  inputFormat="yyyy-MM-dd"
  value={stateDate}
  onChange={(date) => updateAvailableDate(date)}
  renderInput={(params) => (
    <TextField
      {...params}
    />
  )}
  onClose={() => hideModal()}
  clearText="Clear me"
  onAccept={(value) => handleSave(value)}
/>

See all the api settings here. https://mui.com/api/date-picker/

Frizzle answered 1/2, 2022 at 12:19 Comment(1)
It looks like something changed, I can't find clearable option no longer.Than
P
-3

This is what I did to make the clear function work. I recently found this solution so I might change this in the future... but for now it's fine.

       <MobileDateTimePicker
                ...
                clearable
                clearText="Clear"
                onChange={(newScheduleDateTime) => {
                  if (newScheduleDateTime) {
                    setScheduleDateTime(newScheduleDateTime);
                  } else {
                    setScheduleDateTime(null);
                  }
                }}
              />
Promote answered 8/4, 2022 at 15:10 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.