Isla
Isla

Reputation: 2462

react | redux-form | material-ui | how to combine DatePicker with my form

After solving some problems, I stuck with sending DatePicker data to my form. In my form I use mostly elements from redux-form-material-ui, but DatePicker is not a part of it.

I found 2 ways of creating DatePicker component with redux-form.

<Field
  name="startDate"
  autoOk={true}
  floatingLabelText="startDate"
  component={(startDate) => {
    return <DatePicker {...startDate} />;
  }}
  onChange={(event, date) => {console.log(date);}}
/>

and

<DatePicker
  name="startDate"
  autoOk={true}
  floatingLabelText="startDate"
  onChange={(event, date) => {console.log(date)}} />

The problem is that I don't know the way to update the form data with it. The first example even doesn't show the picked date in text field. I can see in form.myForm store, that I made date field active, but it is never updated with picked date. The second shows picked date, but it is not a part of form.myForm object...

I found some examples in internet (e.g. https://github.com/erikras/redux-form/issues/364 ) but there is no fields object in props, so cannot call this.props.fields.startDate.onChange.

I'm not sure what is a good way of working with redux-form and material-ui, as there is not many working examples. I started to think of making a wrapper to EVERY component I use, which will provide onChange method, which will update my store with any change made in form. But then I don't need redux-form anymore, so I think there must some other solution, I could use.

"react": "15.1.0",
"react-tap-event-plugin": "1.0.0",
"redux": "3.0.5",
"redux-form": "^6.0.0-alpha.4",
"redux-form-material-ui": "^2.0.0",

Upvotes: 6

Views: 4669

Answers (4)

bh4r4th
bh4r4th

Reputation: 4420

Not just for this Datepicker but for any custom input, create a separate component to manage the input type and process. Which makes easy to feed your redux-form fields. This is the simple process I was taught by my senior developers when I was a Grad.

In your case, firstly import following additional libraries to your redux-form component

import moment from 'moment'
import { change } from 'redux-form'  //We use the change to dispatch the own props of the redux-form component to resetDateField

Create a separate component by importing DatePicker in it. And your component will look something like this:

const datePickerInput = ({input,name,label,...props}) => {
 return (
  <div>
   <label htmlFor={input.name}> 
    <span>
     {label}
    </span> 
   </label>
   <div>
      <DatePicker
          className='form-control'
          {...input}
          {...props}
      />
   </div>
  </div>
 )
} 

Now feed this component to your redux-form field's component.

<Field
  name = "startDate"
  label = "Start Date"
  dateFormat = 'MMM Do YY'
  component={datePickerInput}
  selected = {/*pass state value of startDate or pass some default null for startDate if nothing selected*/}
  onChange={ (date) => {this.handleChangeStartDate(date, 'startDate')} } //bind this function in constructor and also setState value for your start date as null or some default 
/>

the onChange function is to be handled something like this using moment:

handleChangeStartDate(date, target) {
    const {resetDateField } = this.props
    this.setState({
      [target]: moment(date)
    })
    resetDateField('startDate', '' )
  }

Now hook this resetDateField in your reduxForm @connect by passing dispatch and ownProps and returning resetDateField value expecting a dispatch of change for current form, field, and field value that you want to change using this resetDateField.

Upvotes: 1

pnv
pnv

Reputation: 3135

import React from 'react';
import DatePicker from 'material-ui/DatePicker';

export default ({ input, label, meta: { touched, error }, ...custom }) => {
    return (
        <DatePicker
          onChange={(e, val) => {return input.onChange(val)}}
          {...custom}
          value={input.value}
        />
);
}

Considering this as in file renderDatePicker.js, usage would be,

<Field name="created_on" component={RenderDatePicker} floatingLabelText="Created Date"/>

Where Field is imported from redux-form. Remember to provide {created_on: new Date('someiso8601')} in this.props.initialize to autopopulate it.

Upvotes: 5

Andrew Chaa
Andrew Chaa

Reputation: 6358

I used react-datepicker with redux form. The key was to set "selected" property correctly.

const selectedDate = this.props.fields.date.value ?
  moment(this.props.fields.date.value, 'DD/MM/YYYY') :
  moment();

<DatePicker
  {...date}
  className="form-control"
  dateFormat="DD/MM/YYYY"
  selected={selectedDate}
/>

Upvotes: 3

Balzard
Balzard

Reputation: 1286

Here is how I use it in my code.

<DatePicker
    selected={dateField.value}
    onChange={param => dateField.onChange(param)} />

dateField simply comes from:

const {fields: {dateField}, handleSubmit} = this.props;

Upvotes: 2

Related Questions