Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@benhodgson87
Created February 21, 2018 16:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save benhodgson87/63b893aa8419c08c5f8de33fa71b17fd to your computer and use it in GitHub Desktop.
Save benhodgson87/63b893aa8419c08c5f8de33fa71b17fd to your computer and use it in GitHub Desktop.
Reusable React/Redux-Form Layout using HOC
/**
* Basic input field wrapped with FormField HOC
*/
import React from 'react'
import PropTypes from 'prop-types'
import FormFieldWrapper from './FormFieldWrapper'
import './BasicField.css'
const BasicField = ({
id,
input,
type,
limit,
placeholder,
autocomplete,
}) => (
<div className="basic-field">
<input
className="basic-field-input"
id={id}
{...input}
placeholder={placeholder}
type={type}
maxLength={limit}
autoComplete={autocomplete}
/>
{limit > 0 && (
<div className="basic-field-input-counter">
{limit - input.value.length}
</div>
)}
</div>
)
BasicField.propTypes = {
id: PropTypes.string.isRequired,
input: PropTypes.shape({
name: PropTypes.string,
onBlur: PropTypes.func,
onChange: PropTypes.func,
onDragStart: PropTypes.func,
onDrop: PropTypes.func,
onFocus: PropTypes.func,
value: PropTypes.oneOfType([PropTypes.string, PropTypes.array]),
}).isRequired,
type: PropTypes.string,
placeholder: PropTypes.string,
limit: PropTypes.number,
autocomplete: PropTypes.string,
}
BasicField.defaultProps = {
type: 'text',
placeholder: '',
limit: -1,
autocomplete: 'nope',
}
export default FormFieldWrapper(BasicField)
/**
* Redux-Form Field component showing BasicField passed in
*/
<Field
id="brief-name"
name="guidelinesBrief"
type="text"
component={BasicField}
label="Brief Name"
limit={30}
required
/>
/**
* HOC to wrap form fields with a reusable grid layout + form label
*/
import React from 'react'
import PropTypes from 'prop-types'
import { Row, Col } from 'react-flexbox-grid'
import './FormFieldWrapper.css'
const FormFieldWrapper = FormField => {
const wrappedField = ({
id,
label,
required,
meta: { touched, error },
...props
}) => (
<Row className={`form-field ${touched && error && 'hasError'}`}>
<Col xs={12} md={3}>
<label
className={`form-field-label ${required &&
'isRequired'}`}
htmlFor={id}
>
{label}
{required && <span className="form-field-required">Required</span>}
</label>
</Col>
<Col xs={12} md={9}>
<div>
<FormField id={id} {...props} />
</div>
{touched &&
error && <div className="form-field-validation">{error}</div>}
</Col>
</Row>
)
wrappedField.propTypes = {
id: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
required: PropTypes.bool,
meta: PropTypes.shape({
touched: PropTypes.bool,
error: PropTypes.string,
}).isRequired,
}
wrappedField.defaultProps = {
required: false,
}
return wrappedField
}
export default FormFieldWrapper
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment