react-form-in-second
Version:
make form easily, no more painful
152 lines (96 loc) • 2.78 kB
JSX
import 'babel-polyfill'
class Form extends React.Component {
constructor(props) {
super(props)
this.state = {
data : props.initalData || {},
errors: {},
clickedSubmit: false,
}
}
// filterInitalData = (props) => {
// const { initalData } = props
// if (initalData && typeof initalData === 'object') {
// for (let key in initalData) {
// }
// }
// }
onSubmit = (evt) => {
if (evt && evt.preventDefault)
evt.preventDefault()
this.setState({clickedSubmit: true})
const pass = this.validateData()
if (pass && typeof this.props.onSubmit === 'function')
this.props.onSubmit(im.fromJS(this.state.data).toJS())
}
validateData () {
const { validators } = this.state
, errors = {}
, formData = im.fromJS(this.state.data).toJS();
for (let validator of validators) {
const { rule, errMsg, name } = validator;
if (typeof rule !== 'function') {
errors[name] = errMsg;
} else {
const pass = rule(formData[name], formData)
if (!pass) {
errors[name] = errMsg;
}
}
}
this.setState({errors})
if (Object.keys(errors).length) return false;
return true;
}
onInputChange = async (field, value, inputOnChange) => {
let data = im.fromJS(this.state.data).toJS()
data[field] = value
await this.setState({data})
if (this.state.clickedSubmit)
this.validateData()
if (typeof inputOnChange === 'function')
inputOnChange(data, (newData) => this.setState({data: newData}))
if (typeof this.props.onChange === 'function')
this.props.onChange(data, (newData) => this.setState({data: newData}))
}
passValidationToChildren () {
return React.Children.map(this.props.children, child => {
if (typeof child.type !== 'string') {
const inputOnChange = child.props.onChange
const newChild = React.cloneElement(child, {
onChange: (field, value) => this.onInputChange(field, value, inputOnChange),
error: this.state.errors[child.props.name],
getFormData: () => im.fromJS(this.state).toJS(),
value: this.state.data[child.props.name]
})
return newChild
}
return child
})
}
componentWillMount () {
this.collectValidatiors()
}
collectValidatiors = () => {
const validators = []
React.Children.forEach(this.props.children, child => {
if (child.props.validator)
validators.push({
rule: child.props.validator,
errMsg: child.props.errMsg,
name: child.props.name
})
})
this.setState({validators})
}
render () {
const { className, title } = this.props
return (
<form onSubmit={this.onSubmit} className={className || ''}>
{ title && <div className="form-title">{title}</div>}
{this.passValidationToChildren()}
</form>
)
}
}
export default Form