Skip to content

Instantly share code, notes, and snippets.

@joshuaslate
Created October 26, 2016 13:17
Show Gist options
  • Save joshuaslate/4925721a4806a656f7934441617e6e22 to your computer and use it in GitHub Desktop.
Save joshuaslate/4925721a4806a656f7934441617e6e22 to your computer and use it in GitHub Desktop.
A quick rundown of working with Redux-Form 6+
import React, { Component } from 'react';
import { Field, reduxForm } from 'redux-form';
import moment from 'moment';
import DatePicker from 'react-datepicker';
import ReactQuill from 'react-quill';
import MaskedInput from 'react-maskedinput';
export const renderField = (field) => (
<div>
<input {...field.input} type={field.type} placeholder={field.placeholder} className="form-control" />
{field.meta.touched && field.meta.error && <div className="alert alert-error">{field.meta.error}</div>}
</div>
);
export const renderTextArea = (field) => (
<div>
<textarea {...field.input} type={field.type} className="form-control" placeholder={field.placeholder} />
{field.meta.touched && field.meta.error && <div className="alert alert-error">{field.meta.error}</div>}
</div>
);
export const renderSelect = (field) => (
<div>
<select {...field.input} type={field.type} className="form-control" placeholder={field.placeholder}>
{field.children}
</select>
{field.meta.touched && field.meta.error && <div className="alert alert-error">{field.meta.error}</div>}
</div>
);
// Normally not best practice for Redux Forms, but in order to tie custom fields together, we need a hidden field with the field ID
export const renderHidden = (field) => {
field.input.onChange(field.fieldValue);
return (
<div>
<input {...field.input} value={field.fieldValue} type="hidden" />
</div>
);
}
export const renderCustomFields = ({ meta: { touched, error }, customFields = [] }) => {
let fieldType, fieldComponent;
return (
<ul>
{touched && error && <span>{error}</span>}
{customFields.map((addedField, index) => {
switch(addedField.valueType) {
case 'boolean':
fieldType = 'checkbox';
fieldComponent = 'input';
break;
case 'number':
fieldType = 'number';
fieldComponent = renderField;
break;
case 'string':
fieldType = 'text';
fieldComponent = renderField;
break;
};
return (
<li key={index}>
<Field name={`additional[${index}].fieldId`} fieldValue={addedField._id} component={renderHidden} />
<label className="form-label" for="value">{addedField.name}</label>
<Field name={`additional[${index}].value`} className="form-control" type={fieldType} component={fieldComponent} />
</li>
);
})}
</ul>
)
};
export const wysiwygEditor = React.createClass({
_quillModules: {
toolbar: [
[{ 'header': [1, 2, false] }],
['bold', 'italic', 'underline','strike', 'blockquote'],
[{ 'color': [] }, { 'background': [] }],
[{ 'script': 'sub'}, { 'script': 'super' }],
[{ 'font': [] }],
[{ 'align': [] }],
[{'list': 'ordered'}, {'list': 'bullet'}, {'indent': '-1'}, {'indent': '+1'}],
['link', 'image'],
['clean']
]
},
render: function() {
return (
<div className='_quill'>
<ReactQuill theme='snow'
{...this.props.input}
modules={this._quillModules}
toolbar={false} // Let Quill manage toolbar
bounds={'._quill'}>
<div key="editor"
ref="editor"
className="quill-contents border_solid_top"
dangerouslySetInnerHTML={{__html: this.props.input.value}} />
</ReactQuill>
</div>
);
}
});
/**
* Date Picker Field
* @class
* @param {String} label - The text for the form label
* @param {Object} field - The field object
*
* @description - A standard input with a date picker
*/
export const formDatePicker = React.createClass({
getInitialState: function() {
return {
date: moment()
};
},
handleChange: function(date) {
this.setState({
date: date
});
},
render: function() {
const {inline, input, date, label} = this.props;
return (
<div>
{label}
<DatePicker
{...input}
className="form-control"
dateFormat="MM/DD/YYYY"
placeholderText="Select a date"
selected={this.state.date}
onChange={this.handleChange}
/>
</div>
);
}
});
export const maskedInput = React.createClass({
onTextChange: function(value) {
this.props.input.onChange(value);
},
render: function() {
return (
<MaskedInput {...this.props.input} className={this.props.className} mask={this.props.mask} onChange={this.onTextChange} />
);
}
});
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Field, reduxForm } from 'redux-form';
import { renderField, formDatePicker } from './form-fields';
import { sampleAction } from '../../../actions';
const form = reduxForm({
form: 'uniqueNameForForm'
});
class FormComponentName extends Component {
handleFormSubmit(formProps) {
this.props.sampleAction(formProps);
}
render() {
const { handleSubmit, loading } = this.props;
return (
<div>
<form onSubmit={handleSubmit(this.handleFormSubmit.bind(this))}>
<div>
<label>Name</label>
<Field name="name" className="form-control" component={renderField} type="text" />
</div>
<div>
<label>Start Date</label>
<Field name="startDate" className="form-control" component={formDatePicker} type="date" />
</div>
<div>
<label>Finish Date</label>
<Field name="finishDate" className="form-control" component={formDatePicker} type="date" />
</div>
<button type="submit" disabled={loading} className="button button-primary">Add Project Board</button>
</form>
</div>
);
}
}
function mapStateToProps(state) {
return {
sampleState: state.sample.test,
loading: state.sample.loading
};
}
export default connect(mapStateToProps, { sampleAction })(form(FormComponentName));
@anthonybrown
Copy link

wow, thanks so much!

You're the man dude!

God bless!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment