How to use material-ui-pickers KeyboardDatePicker with moment?

Viewed 48514

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?

3 Answers

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;

@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;
Related