mui / mui-x

MUI X: Build complex and data-rich applications using a growing list of advanced React components, like the Data Grid, Date and Time Pickers, Charts, and more!
https://mui.com/x/
4.17k stars 1.3k forks source link

[DatePicker] `mm/dd/yyyy` input format doesn't allow single digit day and months #5755

Closed PraveenPeri closed 2 years ago

PraveenPeri commented 2 years ago

Duplicates

Latest version

Current behavior 😯

We set the inputFormat on the DatePicker to "MM/dd/yyyy" and this won't allow users to enter 1/1/2020. They will have insert a leading zero and enter the value as "01/01/2020". This is kind of annoying to the users

Expected behavior πŸ€”

1/1/2020 or 01/01/2020 should be allowed as inputs

Steps to reproduce πŸ•Ή

Steps:

  1. Configure a DatePicker with "MM/dd/yyyy" format
  2. Try typing 1/ and you will notice it is flagged as invalid date

Context πŸ”¦

The feedback came from a team of members who are testing our forms in and out. This is the most common annoyance reported from the group. We are looking to fix it for better UX

Your environment 🌎

npx @mui/envinfo ``` System: OS: Linux 4.14 Amazon Linux 2 Binaries: Node: 14.15.4 - /usr/bin/node Yarn: Not Found npm: 7.10.0 - /usr/bin/npm Browsers: Edge ```

Order ID πŸ’³ (optional)

33625

LukasTy commented 2 years ago

Hello @PraveenPeri Could you please try using M/d/yyyy as the format instead and see if it helps? At least with date-fns adapter it then seems to work with both 1/1/2000 as well as 01/01/2000. But do note that in this case you will also need to add disableMaskedInput property as we don't support it with such variable length formats.

PraveenPeri commented 2 years ago

Thanks @LukasTy! That worked! However, could you explain the cons of setting disableMaskedInput? The comment on the property says "use it rarely" but I couldn't quite get what's this prop for.

LukasTy commented 2 years ago

@PraveenPeri Using masked input handles the token separator insertion automatically. For example: If you input 01012020 it would correctly translate into 01/01/2020, whereas disabling it would result in the user needing to manually input 01/01/2020 to correctly parse it as date. Such shortcomings with masked input are planned to be mitigated with migration to a different date input component more in line with how native date input works.

PraveenPeri commented 2 years ago

@LukasTy Ah, I see. That sounds like a major shortcoming. If I add a custom validation inside onChange event like this, Do you think that will compensate for this?

const validateSlashes = (inputValue: string | undefined) =>
    setDateError(inputValue && !(/\/.*\//.test(inputValue)) ? "Invalid Date" : "")
LukasTy commented 2 years ago

If you really need the mentioned custom format for the date pickers I would go with something along these lines (given that you are using date-fns):

import * as React from 'react';
import TextField from '@mui/material/TextField';
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
import isValid from 'date-fns/isValid';

export default function BasicDatePicker() {
  const [value, setValue] = React.useState<Date | null>(null);
  const [dateError, setDateError] = React.useState('');

  return (
    <LocalizationProvider dateAdapter={AdapterDateFns}>
      <DatePicker
        label="Basic example"
        value={value}
        inputFormat="M/d/yyyy"
        onChange={(newValue) => {
          if (isValid(newValue)) {
            setValue(newValue);
            setDateError('');
          } else {
            setDateError('Invalid date');
          }
        }}
        disableMaskedInput
        renderInput={(params) => <TextField {...params} error={!!dateError} helperText={dateError} />}
      />
    </LocalizationProvider>
  );
}

Your suggested function would probably work as well, but it does rely on a particular date format, if you don't need to take care of localisation (various date formats), then you could save a fraction of performance by using the simple regex instead of date validity checking util.

Unless @alexfauquette or @flaviendelangle has any better insights on how to best cover such a requirement..? πŸ€”

PraveenPeri commented 2 years ago

@LukasTy Thanks man! I would rather offload these kind of validations to a library which would cover more ground than I did. I am going to close this ticket now. Appreciate your help!