Skip to content

Instantly share code, notes, and snippets.

@iliaznk
Forked from joshuaslate/form-fields.jsx
Created November 7, 2017 07:44
Show Gist options
  • Save iliaznk/8d3318b62908f8546d007e9b3475e774 to your computer and use it in GitHub Desktop.
Save iliaznk/8d3318b62908f8546d007e9b3475e774 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));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment