Skip to content

Instantly share code, notes, and snippets.

@iliaznk
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.

Revisions

  1. @joshuaslate joshuaslate created this gist Oct 26, 2016.
    159 changes: 159 additions & 0 deletions form-fields.jsx
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,159 @@
    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} />
    );
    }
    });
    51 changes: 51 additions & 0 deletions form-sample.jsx
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,51 @@
    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));