You've already forked react-forms
Youhou
This commit is contained in:
5
src/.eslintrc
Normal file
5
src/.eslintrc
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"env": {
|
||||
"jest": true
|
||||
}
|
||||
}
|
||||
49
src/CheckBox.js
Normal file
49
src/CheckBox.js
Normal file
@@ -0,0 +1,49 @@
|
||||
import React, {Component} from 'react';
|
||||
import {FormConsumer} from "./FormContext";
|
||||
import FormItemError from "./FormItemError";
|
||||
|
||||
export default class CheckBox extends Component
|
||||
{
|
||||
render()
|
||||
{
|
||||
return (
|
||||
<FormConsumer>
|
||||
{(data) => this.renderCheckBox(data)}
|
||||
</FormConsumer>
|
||||
)
|
||||
}
|
||||
|
||||
renderCheckBox(data)
|
||||
{
|
||||
let props = {...this.props}
|
||||
if (props.children) delete props.children
|
||||
if (props.onChangeValue) delete props.onChangeValue
|
||||
return (
|
||||
<div className="form-check">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={this.props.value}
|
||||
onChange={(e) => this.props.onChangeValue(e.target.checked)}
|
||||
{...props} />
|
||||
{this.renderLabel(data)}
|
||||
<FormItemError name={this.props.name} data={data} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
renderLabel(data)
|
||||
{
|
||||
if (this.props.children.length) {
|
||||
return (
|
||||
<label className="form-check-label" htmlFor={this.props.id}>{this.props.children}</label>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CheckBox.defaultProps = {
|
||||
name: 'checkbox',
|
||||
id: 'checkbox',
|
||||
className: 'form-check-input',
|
||||
onChangeValue: (checked) => {}
|
||||
}
|
||||
71
src/Form.js
Normal file
71
src/Form.js
Normal file
@@ -0,0 +1,71 @@
|
||||
import React, {Component} from 'react';
|
||||
import FormContext from './FormContext';
|
||||
import {toast} from 'react-toastify';
|
||||
|
||||
export default class Form extends Component
|
||||
{
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
data: props.data
|
||||
}
|
||||
|
||||
this.displayError = true
|
||||
this.handleError(props)
|
||||
}
|
||||
|
||||
componentWillReceiveProps(props)
|
||||
{
|
||||
this.handleError(props)
|
||||
this.setState({
|
||||
data: props.data
|
||||
})
|
||||
}
|
||||
|
||||
handleError(props)
|
||||
{
|
||||
if (props.data && props.data.error && props.toast && this.displayError == true) {
|
||||
toast.error(props.data.error)
|
||||
this.displayError = false
|
||||
}
|
||||
}
|
||||
|
||||
render()
|
||||
{
|
||||
return (
|
||||
<FormContext.Provider value={this.state.data}>
|
||||
<form onSubmit={this._onSubmit}>
|
||||
{this.renderError()}
|
||||
{this.props.children}
|
||||
</form>
|
||||
</FormContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
_onSubmit = (e) => {
|
||||
e.preventDefault()
|
||||
this.props.onSubmit()
|
||||
this.displayError = true
|
||||
return false;
|
||||
}
|
||||
|
||||
renderError()
|
||||
{
|
||||
if (this.state.data && this.state.data.error && !this.props.toast)
|
||||
{
|
||||
return (
|
||||
<p className="alert alert-danger">{this.state.data.error}</p>
|
||||
)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
Form.defaultProps = {
|
||||
data: null,
|
||||
toast: false,
|
||||
onSubmit: () => {
|
||||
console.log('[Form] submitted')
|
||||
}
|
||||
}
|
||||
17
src/FormContext.js
Normal file
17
src/FormContext.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import React, { Component } from 'react'
|
||||
|
||||
const FormContext = React.createContext({ data: null });
|
||||
|
||||
export default FormContext
|
||||
|
||||
export class FormConsumer extends Component
|
||||
{
|
||||
render()
|
||||
{
|
||||
return (
|
||||
<FormContext.Consumer>
|
||||
{(props) => this.props.children(props)}
|
||||
</FormContext.Consumer>
|
||||
)
|
||||
}
|
||||
}
|
||||
14
src/FormItemError.js
Normal file
14
src/FormItemError.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import React, {Component} from 'react';
|
||||
|
||||
export default class FormItemError extends Component
|
||||
{
|
||||
render() {
|
||||
const data = this.props.data
|
||||
|
||||
if (!data || !data.errors || !data.errors[this.props.name]) return null
|
||||
|
||||
return (
|
||||
<p className="text-danger">{data.errors[this.props.name].error}</p>
|
||||
)
|
||||
}
|
||||
}
|
||||
46
src/Input.js
Normal file
46
src/Input.js
Normal file
@@ -0,0 +1,46 @@
|
||||
import React, {Component} from 'react';
|
||||
import {FormConsumer} from "./FormContext";
|
||||
import FormItemError from "./FormItemError";
|
||||
|
||||
export default class Input extends Component
|
||||
{
|
||||
render()
|
||||
{
|
||||
return (
|
||||
<FormConsumer>
|
||||
{(data) => this.renderInput(data)}
|
||||
</FormConsumer>
|
||||
)
|
||||
}
|
||||
|
||||
renderInput(data)
|
||||
{
|
||||
let props = {...this.props}
|
||||
if (props.children) delete props.children
|
||||
if (props.onChangeValue) delete props.onChangeValue
|
||||
return (
|
||||
<div className="form-group">
|
||||
{this.renderLabel(data)}
|
||||
<input onChange={(e) => this.props.onChangeValue(e.target.value)} {...props} />
|
||||
<FormItemError name={this.props.name} data={data} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
renderLabel(data)
|
||||
{
|
||||
if (this.props.label) {
|
||||
return (
|
||||
<label htmlFor={this.props.id}>{this.props.label}</label>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Input.defaultProps = {
|
||||
name: 'input',
|
||||
id: 'input',
|
||||
className: 'form-control',
|
||||
type: 'text',
|
||||
onChangeValue: (text) => {}
|
||||
}
|
||||
27
src/Option.js
Normal file
27
src/Option.js
Normal file
@@ -0,0 +1,27 @@
|
||||
import React, {Component} from 'react';
|
||||
import {OptionGroupConsumer} from "./OptionGroup";
|
||||
|
||||
export default class Option extends Component
|
||||
{
|
||||
render()
|
||||
{
|
||||
return (
|
||||
<OptionGroupConsumer>
|
||||
{(data) => this.renderOption(data)}
|
||||
</OptionGroupConsumer>
|
||||
)
|
||||
}
|
||||
|
||||
renderOption(data)
|
||||
{
|
||||
let props = {...this.props}
|
||||
|
||||
return (
|
||||
<option {...props}>{this.props.children}</option>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Option.defaultProps = {
|
||||
value: 'option'
|
||||
}
|
||||
83
src/OptionGroup.js
Normal file
83
src/OptionGroup.js
Normal file
@@ -0,0 +1,83 @@
|
||||
import React, {Component} from 'react';
|
||||
import {FormConsumer} from './FormContext';
|
||||
import FormItemError from "./FormItemError";
|
||||
|
||||
const OptionGroupContext = React.createContext({});
|
||||
|
||||
export class OptionGroupConsumer extends Component
|
||||
{
|
||||
render()
|
||||
{
|
||||
return (
|
||||
<OptionGroupContext.Consumer>
|
||||
{(props) => this.props.children(props)}
|
||||
</OptionGroupContext.Consumer>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default class OptionGroup extends Component
|
||||
{
|
||||
render()
|
||||
{
|
||||
return (
|
||||
<FormConsumer>
|
||||
{(data) => this.renderOptionGroup(data)}
|
||||
</FormConsumer>
|
||||
)
|
||||
}
|
||||
|
||||
renderOptionGroup(data)
|
||||
{
|
||||
const props = {...this.props}
|
||||
return (
|
||||
<div className="form-group">
|
||||
{this.renderLabel()}
|
||||
<select {...this.props.data} {...props} onChange={(e) => this._onChange(e)}>
|
||||
{this.renderChildren()}
|
||||
</select>
|
||||
<FormItemError name={this.props.name} data={data} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
_onChange = (e) => {
|
||||
if (this.props.multiple) {
|
||||
let value = []
|
||||
const options = e.target.options;
|
||||
for (let i = 0, l = options.length; i < l; i++) {
|
||||
if (options[i].selected) {
|
||||
value.push(options[i].value);
|
||||
}
|
||||
}
|
||||
this.props.onChangeValue(value)
|
||||
}
|
||||
else {
|
||||
this.props.onChangeValue(e.target.value)
|
||||
}
|
||||
}
|
||||
|
||||
renderLabel()
|
||||
{
|
||||
if (!this.props.label) return null
|
||||
|
||||
return (
|
||||
<label htmlFor={this.props.id}>{this.props.label}</label>
|
||||
)
|
||||
}
|
||||
|
||||
renderChildren()
|
||||
{
|
||||
return (
|
||||
<OptionGroupContext.Provider value={{}}>
|
||||
{this.props.children}
|
||||
</OptionGroupContext.Provider>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
OptionGroup.defaultProps = {
|
||||
name: 'select',
|
||||
className: 'form-control',
|
||||
onChangeValue: (value) => {}
|
||||
}
|
||||
48
src/Radio.js
Normal file
48
src/Radio.js
Normal file
@@ -0,0 +1,48 @@
|
||||
import React, {Component} from 'react';
|
||||
import {RadioGroupConsumer} from "./RadioGroup";
|
||||
|
||||
export default class Radio extends Component
|
||||
{
|
||||
render()
|
||||
{
|
||||
return (
|
||||
<RadioGroupConsumer>
|
||||
{(data) => this.renderRadio(data)}
|
||||
</RadioGroupConsumer>
|
||||
)
|
||||
}
|
||||
|
||||
renderRadio(data)
|
||||
{
|
||||
let props = {...this.props}
|
||||
if (props.children) delete props.children
|
||||
|
||||
return (
|
||||
<div className="form-check">
|
||||
<input
|
||||
type="radio"
|
||||
checked={data.value === this.props.value}
|
||||
onChange={(e) => {
|
||||
if (e.target.checked)
|
||||
data.onChangeValue(this.props.value)
|
||||
}}
|
||||
{...props} />
|
||||
{this.renderLabel(data)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
renderLabel(data)
|
||||
{
|
||||
if (this.props.children.length) {
|
||||
return (
|
||||
<label className="form-check-label" htmlFor={this.props.id}>{this.props.children}</label>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Radio.defaultProps = {
|
||||
value: 'option',
|
||||
className: 'form-check-input'
|
||||
}
|
||||
66
src/RadioGroup.js
Normal file
66
src/RadioGroup.js
Normal file
@@ -0,0 +1,66 @@
|
||||
import React, {Component} from 'react';
|
||||
import {FormConsumer} from './FormContext';
|
||||
import FormItemError from "./FormItemError";
|
||||
|
||||
const RadioGroupContext = React.createContext({});
|
||||
|
||||
export class RadioGroupConsumer extends Component
|
||||
{
|
||||
render()
|
||||
{
|
||||
return (
|
||||
<RadioGroupContext.Consumer>
|
||||
{(props) => this.props.children(props)}
|
||||
</RadioGroupContext.Consumer>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default class RadioGroup extends Component
|
||||
{
|
||||
render()
|
||||
{
|
||||
return (
|
||||
<FormConsumer>
|
||||
{(data) => this.renderRadioGroup(data)}
|
||||
</FormConsumer>
|
||||
)
|
||||
}
|
||||
|
||||
renderRadioGroup(data)
|
||||
{
|
||||
return (
|
||||
<div className="form-options mb-3">
|
||||
{this.renderLabel()}
|
||||
{this.renderChildren()}
|
||||
<FormItemError name={this.props.name} data={data} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
renderLabel()
|
||||
{
|
||||
if (!this.props.label) return null
|
||||
|
||||
return (
|
||||
<p className="mb-0 mt-2">{this.props.label}</p>
|
||||
)
|
||||
}
|
||||
|
||||
renderChildren()
|
||||
{
|
||||
return (
|
||||
<RadioGroupContext.Provider value={{
|
||||
onChangeValue: (value) => this.props.onChangeValue(value),
|
||||
value: this.props.value
|
||||
}}>
|
||||
{this.props.children}
|
||||
</RadioGroupContext.Provider>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
RadioGroup.defaultProps = {
|
||||
name: 'radio',
|
||||
onChangeValue: (value) => {}
|
||||
}
|
||||
13
src/Submit.js
Normal file
13
src/Submit.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import React, {Component} from 'react';
|
||||
|
||||
export default class Submit extends Component {
|
||||
render() {
|
||||
return (
|
||||
<button type="submit" {...this.props}>{this.props.children}</button>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Submit.defaultProps = {
|
||||
className: 'btn btn-primary'
|
||||
}
|
||||
44
src/TextArea.js
Normal file
44
src/TextArea.js
Normal file
@@ -0,0 +1,44 @@
|
||||
import React, {Component} from 'react';
|
||||
import {FormConsumer} from "./FormContext";
|
||||
import FormItemError from "./FormItemError";
|
||||
|
||||
export default class TextArea extends Component
|
||||
{
|
||||
render()
|
||||
{
|
||||
return (
|
||||
<FormConsumer>
|
||||
{(data) => this.renderTextArea(data)}
|
||||
</FormConsumer>
|
||||
)
|
||||
}
|
||||
|
||||
renderTextArea(data)
|
||||
{
|
||||
let props = {...this.props}
|
||||
if (props.onChangeValue) delete props.onChangeValue
|
||||
return (
|
||||
<div className="form-group">
|
||||
{this.renderLabel(data)}
|
||||
<textarea onChange={(e) => this.props.onChangeValue(e.target.value)} {...props} />
|
||||
<FormItemError name={this.props.name} data={data} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
renderLabel(data)
|
||||
{
|
||||
if (this.props.label) {
|
||||
return (
|
||||
<label htmlFor={this.props.id}>{this.props.label}</label>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TextArea.defaultProps = {
|
||||
name: 'textarea',
|
||||
id: 'textarea',
|
||||
className: 'form-control',
|
||||
onChangeValue: (text) => {}
|
||||
}
|
||||
13
src/index.js
Normal file
13
src/index.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import CheckBox from './CheckBox'
|
||||
import Form from './Form'
|
||||
import Input from './Input'
|
||||
import Option from './Option'
|
||||
import OptionGroup from './OptionGroup'
|
||||
import Radio from './Radio'
|
||||
import RadioGroup from './RadioGroup'
|
||||
import Submit from './Submit'
|
||||
import TextArea from './TextArea'
|
||||
|
||||
export {
|
||||
CheckBox, Form, Input, Option, OptionGroup, RadioGroup, Radio, Submit, TextArea
|
||||
}
|
||||
Reference in New Issue
Block a user