Skip to content

Instantly share code, notes, and snippets.

@gradosevic
Forked from insin/app.jsx
Created April 28, 2016 06:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gradosevic/a10d3e9c6ad522213effc597e994d279 to your computer and use it in GitHub Desktop.
Save gradosevic/a10d3e9c6ad522213effc597e994d279 to your computer and use it in GitHub Desktop.
React Form Handling - handleFormInputChange (Live version: http://bl.ocks.org/insin/raw/082c0d88f6290a0ea4c7/)
var INPUT_TYPES = 'color|date|datetime|datetime-local|file|month|number|password|range|search|tel|text|time|url|week'.split('|')
var App = React.createClass({
getInitialState: function() {
return {}
},
onChange: handleFormInputChange,
render: function() {
return <form className="pure-form pure-form-stacked" onChange={this.onChange}>
<div className="pure-control-group">
<input name="input" placeholder="input"/>
</div>
{INPUT_TYPES.map(function(type) {
var name = 'input[' + type + ']'
return <div className="pure-control-group">
<input type={type} name={name} placeholder={name}/>
</div>
}.bind(this))}
<div className="pure-control-group">
<textarea name="textarea" placeholder="textarea"></textarea>
</div>
<div className="pure-control-group">
<label className="pure-checkbox">
<input type="checkbox" name="checkbox"/> Single checkbox
</label>
</div>
<div className="pure-control-group">
<label className="pure-checkbox">
<input type="checkbox" name="checkbox-multiple" value="1"/> Multi-checkbox 1
</label>
<label className="pure-checkbox">
<input type="checkbox" name="checkbox-multiple" value="2"/> Multi-checkbox 2
</label>
<label className="pure-checkbox">
<input type="checkbox" name="checkbox-multiple" value="3"/> Multi-checkbox 3
</label>
</div>
<div className="pure-control-group">
<label className="pure-radio">
<input type="radio" name="radio" value="1"/> Radio 1
</label>
<label className="pure-radio">
<input type="radio" name="radio" value="2"/> Radio 2
</label>
</div>
<div className="pure-control-group">
<select name="select-one">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
</select>
</div>
<div className="pure-control-group">
<select name="select-multiple" multiple>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
</select>
</div>
<pre>this.state: {JSON.stringify(this.state, null, 2)}</pre>
</form>
}
})
React.render(<App/>, document.getElementById('app'))
/*
Assumptions
-----------
These aren't prescriptive, they're just a log of the decisions that had to be
made when writing the code below:
* User input maps directly to context component state by name
* State for the following inputs which represent multiple values with the same
name is an Array of Strings:
* Multiple selects
* Checkbox groups
* If a checkbox is not part of a same-named group, its state is Boolean
* The user agent implements/has:
* Array.isArray()
* Array.prototype.indexOf()
* RadioNodeList, NodeList or HTMLCollection type for same-named inputs in form.elements
*/
function handleFormInputChange(e) {
var el = e.target
var name = el.name
var type = el.type
var stateChange = {}
if (type == 'select-multiple') {
var selectedOptions = []
for (var i = 0, l = el.options.length; i < l; i++) {
if (el.options[i].selected) {
selectedOptions.push(el.options[i].value)
}
}
stateChange[name] = selectedOptions
}
else if (type == 'checkbox') {
var objType = Object.prototype.toString.call(el.form.elements[name])
if (objType == '[object RadioNodeList]' || objType == '[object NodeList]' || objType == '[object HTMLCollection]') {
var checkedBoxes = (Array.isArray(this.state[name]) ? this.state[name].slice() : [])
if (el.checked) {
checkedBoxes.push(el.value)
}
else {
checkedBoxes.splice(checkedBoxes.indexOf(el.value), 1)
}
stateChange[name] = checkedBoxes
}
else {
stateChange[name] = el.checked
}
}
else {
stateChange[name] = el.value
}
this.setState(stateChange)
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React Form Handling - handleFormInputChange</title>
<script src="http://fb.me/react-0.12.0.js"></script>
<script src="http://fb.me/JSXTransformer-0.12.0.js"></script>
<link rel="stylesheet" href="http://yui.yahooapis.com/pure/0.5.0/pure-min.css">
<link rel="stylesheet" href="http://yui.yahooapis.com/pure/0.5.0/grids-responsive-min.css">
<style>
.content { max-width: 800px; margin: 0 auto; }
</style>
</head>
<body>
<div class="content">
<div id="app"></div>
</div>
<script src="handleFormInputChange.js"></script>
<script type="text/jsx" src="app.jsx"></script>
<a href="https://gist.github.com/insin/082c0d88f6290a0ea4c7"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub"></a>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment