Skip to content

Instantly share code, notes, and snippets.

@Hamzali
Last active January 4, 2018 12:20
Show Gist options
  • Save Hamzali/7b7dfec186ef9ade26b1d62d695be96c to your computer and use it in GitHub Desktop.
Save Hamzali/7b7dfec186ef9ade26b1d62d695be96c to your computer and use it in GitHub Desktop.
React JSON Form
import React, { Component } from "react";
import PropTypes from "prop-types";
import styled from "styled-components";
import { INPUT_TYPES } from "../../constants";
import { isEmpty } from "../../utils";
import Input from "./input";
import Button from "./button";
import Textarea from "./textarea";
import Checkbox from "./checkbox";
import Selector from "./selector";
import { DatePicker } from "../date-picker";
import Label from "./label";
import Error from "./error";
const { BOOL, TEXT, NUMBER, DATE, SELECTOR, LONG_TEXT } = INPUT_TYPES;
const FieldWrapper = styled.div`
margin: 0.5em 0;
`;
const FieldComponent = ({ children, label, error, noBreak }) => (
<FieldWrapper>
{label && <Label text={label} />}
{!noBreak && <br />}
{children}
<br />
{error && <Error text={error} />}
</FieldWrapper>
);
class Form extends Component {
constructor(props) {
super(props);
const { inputFields } = props;
const stateObj = inputFields.reduce((acc, elem) => {
acc[elem.key] = "";
return acc;
}, {});
this.state = {
err: "",
data: { ...stateObj }
};
}
handleChange(key) {
return val => {
const obj = { data: { ...this.state.data } };
obj.data[key] = val;
this.setState(obj);
};
}
handleSubmit(e) {
e.preventDefault();
this.props.onSubmit(this.state.data);
}
renderFormElements() {
const { inputFields } = this.props;
return inputFields.map((field, _key) => {
const { type, label, key, validator, defaultValue, props } = field;
const value = this.state.data[key];
const error = validator && validator(value);
let input = null;
let noBreak = false;
switch (type) {
case TEXT:
input = (
<Input
key={_key}
value={value || defaultValue}
onChange={this.handleChange(key)}
/>
);
break;
case LONG_TEXT:
input = (
<Textarea
key={_key}
value={value || defaultValue}
onChange={this.handleChange(key)}
/>
);
break;
case SELECTOR:
input = (
<Selector
sections={props.sections}
key={_key}
value={value || defaultValue}
onSelect={this.handleChange(key)}
/>
);
break;
case BOOL:
noBreak = true;
input = (
<Checkbox
key={_key}
value={value || defaultValue}
onChange={this.handleChange(key)}
/>
);
break;
case DATE:
input = (
<DatePicker
key={_key}
value={value || defaultValue}
onChange={this.handleChange(key)}
/>
);
break;
case NUMBER:
input = (
<Input
type="number"
key={_key}
value={value || defaultValue}
onChange={this.handleChange(key)}
/>
);
break;
default:
break;
// add other type of inputs.
}
return (
<FieldComponent
key={_key}
label={label}
error={error}
noBreak={noBreak}
>
{input}
</FieldComponent>
);
});
}
render() {
return (
<form>
{this.renderFormElements()}
<Button green text="Submit" onClick={e => this.handleSubmit(e)} />
</form>
);
}
}
Form.propTypes = {
// formTitle: PropTypes.string,
inputFields: PropTypes.arrayOf(
PropTypes.shape({
label: PropTypes.string,
defaultValue: PropTypes.any,
key: PropTypes.string.isRequired,
type: PropTypes.oneOf([BOOL, TEXT, NUMBER, DATE, SELECTOR, LONG_TEXT])
.isRequired,
validator: PropTypes.func,
props: PropTypes.object
})
).isRequired,
onSubmit: PropTypes.func,
validateOnSubmit: PropTypes.func
};
Form.defaultProps = {
// formTitle: 'Form Title',
inputFields: [
{
label: "Name",
key: "name",
type: TEXT,
validator: val => {
if (isEmpty(val)) {
return null;
}
if (val.length < 5) {
return "Name cannot be shorter than 5!";
}
return null;
}
}
],
validateOnSubmit: data => {
if (data.name) {
return "Name field should not be empty!";
}
},
onSubmit: data => console.log(data)
};
export default Form;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment