Material-ui-pickers: Redux-form integration

Created on 28 Dec 2017  路  9Comments  路  Source: mui-org/material-ui-pickers

Are there any docs on how to integrate these awesome pickers with redux-form?
Has anyone done this before? Thanks!

question

Most helpful comment

@dmtrKovalenko could you please reopen this?

BTW This is how I`m using this lib with redux form

export const DateTimePickerRow = props => {
  const {
    timezone,
    showErrorsInline,
    dispatch,
    input: { onChange, value },
    meta: { touched, error },
    ...other
  } = props

  const showError = showErrorsInline || touched
  const valueWithTimeZone = momentTz.tz(value, timezone)

  return (
    <DateTimePicker
      error={!!(showError && error)}
      helperText={showError && error}
      value={valueWithTimeZone}
      onChange={onChange}
      {...other}
    />
  )
}

Apparently it does not work anymore with the latest master.

All 9 comments

const renderDateTime = ({ input, ...rest }) => {
    return (
        <DateTimePicker
            {...input}
            {...rest}
            value={new Date(input.value)}
            onChange={(event, value) => {
                console.log(event, value)
                return input.onChange(event.toString())
            }}
        />
    )
}

But I get this error, and the date format is messed up. Please help

warning.js:33 Warning: React does not recognize the `invalidDateMessage` prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase `invaliddatemessage` instead. If you accidentally passed it from a parent component, remove it from the DOM element.

This error actually doesn鈥檛 related to redux form, we will fix that error in the next release(today), but it should works. Please provide sandbox if you are facing exception.

BTW This is how I`m using this lib with redux form

export const DateTimePickerRow = props => {
  const {
    timezone,
    showErrorsInline,
    dispatch,
    input: { onChange, value },
    meta: { touched, error },
    ...other
  } = props

  const showError = showErrorsInline || touched
  const valueWithTimeZone = momentTz.tz(value, timezone)

  return (
    <DateTimePicker
      error={!!(showError && error)}
      helperText={showError && error}
      value={valueWithTimeZone}
      onChange={onChange}
      {...other}
    />
  )
}

@dmtrKovalenko can you provide a sample how you use this? I'm unable to make this work. When this gets called I get

Uncaught TypeError: Cannot read property 'onChange' of undefined

I see that onChange is on the props. The error is apparently in this line:

input: { onChange, value },
Thanks in advance

@ferarnoled Its jus a part of redux form WrappedFieldProps of redux-form v7.0.2

@dmtrKovalenko could you please reopen this?

BTW This is how I`m using this lib with redux form

export const DateTimePickerRow = props => {
  const {
    timezone,
    showErrorsInline,
    dispatch,
    input: { onChange, value },
    meta: { touched, error },
    ...other
  } = props

  const showError = showErrorsInline || touched
  const valueWithTimeZone = momentTz.tz(value, timezone)

  return (
    <DateTimePicker
      error={!!(showError && error)}
      helperText={showError && error}
      value={valueWithTimeZone}
      onChange={onChange}
      {...other}
    />
  )
}

Apparently it does not work anymore with the latest master.

I want to share this with you guys. I've done this today. I haven't test everything yet (like validations) but I think it's a good start.

Package versions:

  • react: 16.8.6
  • redux-form: 8.1.0
  • @material-ui/core: 3.9.3
  • material-ui-pickers: 2.2.4
import React from 'react'
import PropTypes from 'prop-types'
import { DatePicker } from 'material-ui-pickers'

const DatePickerField = ({
  inputFormat,
  dateParser,
  input,
  label,
  meta: { touched, invalid, error },
  dateFormatter,
  ...rest,
}) => {
  return (
    <DatePicker
      error={touched && invalid}
      format={inputFormat}
      helperText={touched && error}
      label={label}
      onChange={val => input.onChange(dateParser(val))}
      value={dateFormatter(input.value)}
      {...rest}  />
  )
}

DatePickerField.propTypes = {
  dateFormatter: PropTypes.func,
  dateParser: PropTypes.func,
  input: PropTypes.object.isRequired,
  inputFormat: PropTypes.string,
  label: PropTypes.string.isRequired,
  meta: PropTypes.object.isRequired,
}

DatePickerField.defaultProps = {
  dateFormatter: v => v.replace(/-/g, '/'),
  dateParser: v => v.getFullYear() + '-' + ('0' + (v.getMonth() + 1)).slice(-2) + '-' + ('0' + v.getDate()).slice(-2),
  inputFormat: 'dd/MM/yyyy',
}

export default DatePickerField

dateFormatter and dateParser are functions to work around this https://dev.to/kspeakman/oh-javascript--3404 on my use case. You may need to change these to adapt to your needs.

Usage example (year/month picker):

<Field
  name={name}
  label='Per铆odo'
  validate={[ required ]}
  component={DatePickerField}
  inputFormat='MMM/yyyy'
  views={['year', 'month']} />

@dmtrKovalenko Hi
I just faced with some issue that related to this one and I do not want to open new issue may be you will reopen this one.
I use redux-form latest version 8.2.6 and your pickers 3.2.8. I use Keyboard picker in my app.
My picker is connected to redux-form as in your example and all works good if the date is picked from calendar, but if I am trying to input date by keyboard it will validated by redux form only once and the reason for this is the fact that each time picker will send Invalid Date {} to input change event

e.g
1_/__/____ => Invalid Date=> the form is validated
13/__/____ => Invalid Date=> the form is not validated
13/13/____ => Invalid Date=> the form is not validated
13/13/1313 => Invalid Date=> the form is not validated, but here I need the validation to run in order to show error to user, but it is not happens cause redux form gets same value to validate and does not rerun form validation

So I guess in your component you use something like new Date(value), which provides such output (Invalid Date {}).
Is there todo something with it e.g. some custom parser option for onChange keyboard event or may be disable parsing at all cause in my case I do parsing in form validation
Thanks for the help

I'm currently using those pickers with redux form in a project.

Package versions:

  • react: 16.12.0
  • @material-ui/core: 4.9.2,
  • @material-ui/pickers: 3.2.10
  • redux-form: 8.2.6
  • date-fns: 2.9.0
  • typescript: 3.7.5

Since I have KeyboardTimePicker and KeyboardDatePicker I just made HOC that lets me use them as follows:

// KeyboardDatePicker 
import { KeyboardDatePicker } from '@material-ui/pickers' 
import reduxFieldDatePickerWrapper from '../../containers/hocs/reduxFieldDatePickerWrapper'

export default reduxFieldDatePickerWrapper(KeyboardDatePicker)

Here's HOC itself:

// reduxFieldDatePickerWrapper
import React, { useEffect, useState } from 'react'
import { WrappedFieldProps } from 'redux-form'
import parse from 'date-fns/parse'

type OwnProps = {
    format: string
}

const reduxFieldDatePickerWrapper = <T extends {}>(
    WrappedComponent: React.ComponentType<T>,
): React.ComponentType<T & WrappedFieldProps> => (props: WrappedFieldProps & T & OwnProps) => {
    const {
        input,
        meta: { touched, invalid, error },
        format,
        ...rest
    } = props

    const parser = format
        ? (dateValue: string) => parse(dateValue, format, new Date())
        : (dateValue: string) => new Date(dateValue)

    const [selectedDate, setValue] = useState(() => {
        return input.value ? 
        parser(input.value)
        : null
    })

    useEffect(() => {
        if (input.value) {
            setValue(parser(input.value))
        } else {
            setValue(null)
        }
    }, [input.value])

    return (
        <WrappedComponent
            autoOk
            {...input}
            value={selectedDate}
            error={touched && invalid}
            helperText={touched && error}
            invalidDateMessage="Invalid date format"
            onChange={setValue}
            format={format}
            {...((rest as unknown) as T)}
        />
    )
}

export default reduxFieldDatePickerWrapper

As you can see, if I need to parse data from redux state input.value , I use date-fns parser. You can replace it with your own.
Didn't try to implement async validation on this component yet, so errors weren't tested

Was this page helpful?
0 / 5 - 0 ratings

Related issues

nicky-dev picture nicky-dev  路  3Comments

sakulstra picture sakulstra  路  3Comments

katy6514 picture katy6514  路  3Comments

idrm picture idrm  路  3Comments

dandv picture dandv  路  3Comments