How to use material-ui-pickers KeyboardDatePicker with moment?
Asked Answered
F

3

17

I am using KeyBoardDatePicker from material-ui-pickers with moment utils for a DatePicker.

import React, { Fragment, useState } from "react";
import {
  MuiPickersUtilsProvider,
  KeyboardDatePicker
} from "@material-ui/pickers";
import MomentUtils from "@date-io/moment";
import moment from "moment";

function KeyboardDatePickerExample(props) {
  const [selectedDate, handleDateChange] = useState(new Date());

  return (
    <Fragment>
      <MuiPickersUtilsProvider libInstance={moment} utils={MomentUtils}>
        <KeyboardDatePicker
          autoOk={true}
          showTodayButton={true}
          value={selectedDate}
          format="D MMM, YYYY"
          onChange={handleDateChange}
          minDate={moment().subtract(6, "months")}
          maxDate={moment()}
        />
      </MuiPickersUtilsProvider>
    </Fragment>
  );
}

export default KeyboardDatePickerExample;

But it's not working properly.

First, it's not showing the date format properly

Initial view of the picker

and when I try to edit, it it's showing random text and an error invalid date format.

View of the picker when I try to edit

Here is a sandbox that reproduces the issue.

What am I doing wrong?

EDIT:

After seeing the answer by Nico, I changed the version of date-io/moment to 1.3.13

Now, the date format is displayed properly

enter image description here

But the edit propblem still exists. What can I do to fix it?

Fecula answered 9/3, 2020 at 12:44 Comment(2)
Did you manage to solve the edit problem?Brecher
@Brecher I posted an answer. Please have a lookFecula
F
24

This is the fix provided by a colleague of mine. He used inputValue and value props of KeyboardDatePicker. value takes date object and inputValue takes formatted date string. And also used rifmFormatter prop as follows to fix the edit issue. I have also updated the sandbox

import React, { Fragment, useState } from "react";
import {
  MuiPickersUtilsProvider,
  KeyboardDatePicker
} from "@material-ui/pickers";
import MomentUtils from "@date-io/moment";
import moment from "moment";

function KeyboardDatePickerExample(props) {
  const [selectedDate, setDate] = useState(moment());
  const [inputValue, setInputValue] = useState(moment().format("YYYY-MM-DD"));

  const onDateChange = (date, value) => {
    setDate(date);
    setInputValue(value);
  };

  const dateFormatter = str => {
    return str;
  };

  return (
    <Fragment>
      <MuiPickersUtilsProvider libInstance={moment} utils={MomentUtils}>
        <KeyboardDatePicker
          autoOk={true}
          showTodayButton={true}
          value={selectedDate}
          format="YYYY-MM-DD"
          inputValue={inputValue}
          onChange={onDateChange}
          rifmFormatter={dateFormatter}
        />
      </MuiPickersUtilsProvider>
    </Fragment>
  );
}

export default KeyboardDatePickerExample;
Fecula answered 28/5, 2020 at 6:44 Comment(2)
thank you for posting your answer! I noticed that problem in my case is that I have a KeyboardDatePicker inside mui's Dialog. I believe this re-renders the Dialog component somehow on a date change causing the error. However everything works just fine when KeyboardDatePicker is outside the mui's Dialog component. I post this comment just in case someone has similar problem.Brecher
<flame>Please allow a small flame -- as nearly as I can tell, this entire environment is a massive job-and-income-security effort created by programmers for programmers. I got here in March of 2021 because I want what I thought was a simple and easy widget -- a date picker that depicts a given date as '03/12/2021'. I think that is a format string of "mm/dd/yyyy" in any reasonable component in any language that handles dates. I've been at this for nearly a day now with no joy. BTW, it does NOT work with the above code. Is this REALLY the best that we can do? </flame>Blanco
I
5

You can't use material UI picker v3 and @date-io/moment v2 together. You have to use the v1.x version of @date-io/moment.

Here is some more information about this topic:
https://material-ui-pickers.dev/getting-started/installation

Best regards
Nico

Indoors answered 9/3, 2020 at 15:49 Comment(2)
I changed the version of date-io/moment to 1.3.13. Now, the date format is displayed properly but the edit problem still exists. How can I fix that?Fecula
Does MUI Core v5.0.0 also require v1.x version of @date-io/moment ? In MUI Core v5.0.0, @material-ui/pickers moved to @mui/lab but I do not see any information at mui.com/components/date-picker about the compatibility with any particular version of @date-io/moment .Jacoby
I
2

@troglodyte07 's answer fixed the issue of date formatting. However, the caret is going backward when typing English characters or commas. It is because the default date format does not accept English characters and special characters like commas.

The edit issue can be fixed by setting rifmFormatter and refuse properties to override the default date format. For example, to edit date with this date format "D MMM, YYYY", we need to set rifmFormatter and refuse properties by the regular expressions which allow English characters, commas, spaces, and numbers.

/[^ ,a-zA-Z0-9]+/gi

For other date formats, the regular expressions should be customized.

I have forked @troglodyte07 's sandbox and improved it: datepicker-edit-value-custom-format

import React, { Fragment, useState } from "react";
import {
  MuiPickersUtilsProvider,
  KeyboardDatePicker
} from "@material-ui/pickers";
import MomentUtils from "@date-io/moment";
import moment from "moment";

function KeyboardDatePickerExample(props) {
  const [selectedDate, setDate] = useState(moment());
  const [inputValue, setInputValue] = useState(moment().format("D MMM, YYYY"));

  const onDateChange = (date, value) => {
    setDate(date);
    setInputValue(value);
  };

  return (
    <Fragment>
      <MuiPickersUtilsProvider libInstance={moment} utils={MomentUtils}>
        <KeyboardDatePicker
          autoOk={true}
          showTodayButton={true}
          value={selectedDate}
          format="D MMM, YYYY"
          inputValue={inputValue}
          onChange={onDateChange}
          rifmFormatter={(val) => val.replace(/[^ ,a-zA-Z0-9]+/gi, "")}
          refuse={/[^ ,a-zA-Z0-9]+/gi}
        />
      </MuiPickersUtilsProvider>
    </Fragment>
  );
}

export default KeyboardDatePickerExample;
Inextensible answered 17/8, 2022 at 3:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.