Skip to content

Instantly share code, notes, and snippets.

@bryzettler
Last active September 5, 2017 15:26
Show Gist options
  • Save bryzettler/4c064da68c905427ee83452030395b05 to your computer and use it in GitHub Desktop.
Save bryzettler/4c064da68c905427ee83452030395b05 to your computer and use it in GitHub Desktop.
// @flow
import React from 'react';
import {
Form,
Input,
Checkbox,
Radio,
Select,
Dropdown,
TextArea,
Label,
} from 'semantic-ui-react';
/**
* Ment to work in tenem with redux-form
*/
const FormField = ({
input,
label,
type,
meta: { touched, error },
...field,
}) => {
const { width, inline, errorPosition, labelVisible } = field;
const handleValueChange = (key) => (e, obj) => {
const value = obj[key];
input.onChange(value);
};
const renderField = () => ({
'text': <Input {...input} {...field} />,
'textarea': <TextArea {...input} {...field} />,
'select': (
<Select
{...input}
{...field}
onChange={handleValueChange('value')}
/>
),
'checkbox': (
<Checkbox
{...input}
{...field}
label={label || input.value}
onChange={handleValueChange('checked')}
/>
),
'radio': (
<Radio
{...input}
{...field}
label={label || input.value}
onChange={handleValueChange('value')}
/>
),
'dropdown': (
<Dropdown
{...input}
{...field}
search
selection
multiple
onBlur={handleValueChange('value')}
onChange={handleValueChange('value')}
/>
)
}[type]);
const getErrorPointerPosition = () => ({
"left": "right",
"right": "left",
"top": "below",
"bottom": "above",
undefined: (() => inline ? "left" : "above")(),
}[errorPosition])
return (
<Form.Field
width={width}
inline={inline || (!!errorPosition && ["left", "right"].includes(errorPosition))}
>
{/*
If input is checkbox || radio we dont want to show the label as it
also appears next the input itself.
*/}
{(labelVisible !== false && !["checkbox", "radio"].includes(type)) && (
<label htmlFor={field.name}>{label}</label>
)}
{/*
Render error label above the input if errorPosition is left || top
*/}
{touched && (error && ["left", "top"].includes(errorPosition) && (
<Label basic color="red" pointing={getErrorPointerPosition()}>{error}</Label>
))}
{renderField()}
{/*
if type is checkbox || radio that is not inline and errorPosition is bottom || undefined (default)
we require a <br /> to bump the error to the next line
*/}
{
(error && ["checkbox", "radio"].includes(type)) &&
(!inline && ["bottom", undefined].includes(errorPosition)) &&
(<br />)
}
{/*
Render error label below the input if errorPosition is right || bottom || undefined (default)
*/}
{touched && (error && ["right", "bottom", undefined].includes(errorPosition) && (
<Label basic color="red" pointing={getErrorPointerPosition()}>{error}</Label>
))}
</Form.Field>
)
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment