Skip to content

Instantly share code, notes, and snippets.

@gearnode
Last active February 17, 2018 21:33
Show Gist options
  • Save gearnode/1bfafc0cd060fbc505ff42be38f8169a to your computer and use it in GitHub Desktop.
Save gearnode/1bfafc0cd060fbc505ff42be38f8169a to your computer and use it in GitHub Desktop.
Generic React AJAX Form
import React, { Component } from 'react'
import PropTypes from 'prop-types';
import FormObject from './FormObject'
export default class Form extends Component {
static propTypes = {
method: PropTypes.string.isRequired,
action: PropTypes.string.isRequired,
encType: PropTypes.string.isRequired,
serializeForm: PropTypes.func.isRequired,
onResponse: PropTypes.func.isRequired
}
constructor(props) {
super(props)
this.state = { performing: false }
this.handleSubmit = this.handleSubmit.bind(this)
}
preventUserSpam(func) {
if (this.state.performing === false) {
this.setState({performing: true})
func()
this.setState({performing: false})
} else {
console.debug("some action perform please wait...")
}
}
handleSubmit(event) {
event.preventDefault()
const form = event.currentTarget
console.debug("NativeFormValidation disabled => ", form.noValidate)
this.preventUserSpam(_ => {
if (form.checkValidity() === false) {
form.reportValidity()
const formErrors = FormObject.collectErrors(form)
console.warn('formErrors => ', formErrors)
return
}
const fromData = FormObject.collectValues(form)
const serializeForm = this.props.serializeForm
const fetchRequest = { body: serializeForm(fromData),
headers: { 'content-type': this.props.encType },
method: this.props.method }
fetch(this.props.action, fetchRequest).then(this.props.onResponse)
})
}
render() {
return (
<div>
<form method={ this.props.method }
action={ this.props.action }
encType={ this.props.encType }
onSubmit={ this.handleSubmit }
noValidate>
{ this.props.children }
</form>
</div>
)
}
}
export default class FormObject {
static collectValues(form) {
const inputs = form.elements
let data = {}
for (let i = 0; inputs[i] !== undefined; i++)
if (inputs[i].nodeName !== "BUTTON")
data[inputs[i].name] = inputs[i].value
return data
}
static collectErrors(form) {
const inputs = form.elements
let errors = {}
for (let i = 0; inputs[i] !== undefined; i++)
if (inputs[i].nodeName !== "BUTTON")
errors[inputs[i].name] = inputs[i].validationMessage
return errors
}
}
<div>
<h1>Demo Form</h1>
<Form method="post"
action="/bar"
encType="application/json"
onResponse={ this.onResponse }
serializeForm={ this.serializeForm }>
<div>
<input type="text"
name="first_name"
required
maxLength="200"
placeholder="John"
autoComplete="given-name"/>
</div>
<div>
<input type="text"
name="last_name"
required
maxLength="200"
placeholder="Doe"
autoComplete="family-name"/>
</div>
<div>
<input type="email"
name="email"
required
placeholder="[email protected]"
autoComplete="email"/>
</div>
<button>Create</button>
</Form>
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment