Skip to content

Instantly share code, notes, and snippets.

@AoDev

AoDev/App.js Secret

Last active May 22, 2021 02:26
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AoDev/f1f490b50927ed03c357 to your computer and use it in GitHub Desktop.
Save AoDev/f1f490b50927ed03c357 to your computer and use it in GitHub Desktop.
Handling forms in React with Mobx observables
import React, {Component} from 'react'
import PersonForm from './PersonForm'
import {observable} from 'mobx'
import personData from '../data/person'
export default class App extends Component {
constructor (props) {
super(props)
this.person = observable(personData)
}
render () {
return (
<div className="container">
<h1>Handling forms in React with Mobx</h1>
<hr/>
<PersonForm person={this.person}/>
</div>
)
}
}
/**
* asForm Higher Order Component
*/
import React, {Component} from 'react'
export default function asForm (MyComponent, formDataProp) {
return class Form extends Component {
constructor (props) {
super(props)
this.updateProperty = this.updateProperty.bind(this)
}
updateProperty (key, value) {
this.props[formDataProp][key] = value
}
render () {
return <MyComponent {...this.props} updateProperty={this.updateProperty}/>
}
}
}
import React, {Component, PropTypes} from 'react'
import {observer} from 'mobx-react'
@observer
export default class InputCheckboxes extends Component {
constructor (props) {
super(props)
this.onChange = this.onChange.bind(this)
}
onChange (event) {
this.props.onChange(this.props.name, event.target.value)
}
render () {
const {items, name, checkedItems} = this.props
return (
<div className="form-group">
<b>{name}</b>
{
items.map((item) => {
return (
<div className="checkbox" key={`${name}-${item}`}>
<label htmlFor={`${name}-${item}`}>
<input type="checkbox" name={`${name}`} value={item} id={`${name}-${item}`}
checked={checkedItems.indexOf(item) > -1}
onChange={this.onChange}/> {item}
</label>
</div>
)
})
}
</div>
)
}
}
import React, {Component, PropTypes} from 'react'
import {observer} from 'mobx-react'
@observer
export default class InputField extends Component {
constructor (props) {
super(props)
this.onChange = this.onChange.bind(this)
}
onChange (event) {
this.props.onChange(event.target.name, event.target.value)
}
render () {
const input = this.props
return (
<div className="form-group">
<label htmlFor={input.id}>{input.label || input.name}</label>
<input
className="form-control"
id={input.id}
name={input.name}
onChange={this.onChange}
type={input.type}
value={input.value}/>
</div>
)
}
}
InputField.propTypes = {
onChange: PropTypes.func.isRequired
}
InputField.defaultProps = {
type: 'text'
}
import React, {Component, PropTypes} from 'react'
import {observer} from 'mobx-react'
import {InputField} from '../../components'
@observer
export default class PersonAddress extends Component {
constructor (props) {
super(props)
this.updateProperty = this.updateProperty.bind(this)
}
updateProperty (key, value) {
this.props.address[key] = value
}
render () {
const {address} = this.props
return (
<div>
<InputField id="address-city" name="city" value={address.city} onChange={this.updateProperty}/>
<InputField id="address-postal-code" name="postalCode" value={address.postalCode} onChange={this.updateProperty}/>
<InputField id="address-street" name="street" value={address.street} onChange={this.updateProperty}/>
</div>
)
}
}
PersonAddress.propTypes = {
address: PropTypes.shape({
city: PropTypes.string,
postalCode: PropTypes.string,
street: PropTypes.string
})
}
import React, {Component, PropTypes} from 'react'
import {observer} from 'mobx-react'
import asForm from './asForm'
import InputText from './InputText'
@observer
class PersonAddress extends Component {
render () {
const {address, updateProperty} = this.props
return (
<div>
<InputText id="address-city" name="city" value={address.city} onChange={updateProperty}/>
<InputText id="address-postal-code" name="postalCode" value={address.postalCode} onChange={updateProperty}/>
<InputText id="address-street" name="street" value={address.street} onChange={updateProperty}/>
</div>
)
}
}
PersonAddress.propTypes = {
address: PropTypes.shape({
city: PropTypes.string,
postalCode: PropTypes.string,
street: PropTypes.string
})
}
export default asForm(PersonAddress, 'address')
var person = {
fullName: 'John Doe',
job: 'Web Developer',
email: 'john.doe@example.com',
address: {
city: 'Budapest',
postalCode: '1000',
street: 'Reactive street'
}
}
var person = {
fullName: 'John Doe',
address: {
city: 'Budapest',
postalCode: '1000',
street: 'Reactive street'
},
tasks: [
{
id: 1,
name: 'Write the article about forms',
dueDate: 'yesterday'
},
{
id: 2,
name: 'Eat something',
dueDate: 'Now'
},
{
id: 3,
name: 'Go to sleep',
dueDate: 'Soon'
}
]
}
import React, {Component, PropTypes} from 'react'
import {observer} from 'mobx-react'
@observer
export default class PersonForm extends Component {
constructor (props) {
super(props)
this.updateProperty = this.updateProperty.bind(this)
this.onChange = this.onChange.bind(this)
}
updateProperty (key, value) {
this.props.person[key] = value
}
onChange (event) {
this.updateProperty(event.target.name, event.target.value)
}
render () {
const {person} = this.props
return (
<div>
<h1>My Person Form</h1>
<form>
<input type="text" name="fullName" value={person.fullName} onChange={this.onChange}/>
</form>
</div>
)
}
}
import React, {Component, PropTypes} from 'react'
import {observer} from 'mobx-react'
import {InputField} from '../../components'
@observer
export default class PersonForm extends Component {
constructor (props) {
super(props)
this.updateProperty = this.updateProperty.bind(this)
}
updateProperty (key, value) {
this.props.person[key] = value
}
render () {
const {person} = this.props
return (
<div>
<h1>My Person Form</h1>
<form>
<InputField name="fullName" value={person.fullName} onChange={this.updateProperty}/>
<InputField name="job" value={person.job} onChange={this.updateProperty}/>
<InputField name="email" value={person.email} onChange={this.updateProperty}/>
</form>
</div>
)
}
}
import React, {Component, PropTypes} from 'react'
import {observer} from 'mobx-react'
import PersonAddress from './PersonAddress'
import {InputField} from '../../components'
@observer
export default class PersonForm extends Component {
constructor (props) {
super(props)
this.updateProperty = this.updateProperty.bind(this)
}
updateProperty (key, value) {
this.props.person[key] = value
}
render () {
const {person} = this.props
return (
<div>
<h1>My Person Form</h1>
<form>
<InputField name="fullName" value={person.fullName} onChange={this.updateProperty}/>
<InputField name="job" value={person.job} onChange={this.updateProperty}/>
<InputField name="email" value={person.email} onChange={this.updateProperty}/>
<PersonAddress address={person.address} />
</form>
</div>
)
}
}
import React, {Component, PropTypes} from 'react'
import {observer} from 'mobx-react'
import PersonAddress from './PersonAddress'
import PersonTask from './PersonTask'
import {InputField} from '../../components'
@observer
export default class PersonForm extends Component {
constructor (props) {
super(props)
this.updateProperty = this.updateProperty.bind(this)
}
updateProperty (key, value) {
this.props.person[key] = value
}
render () {
const {person} = this.props
return (
<div>
<h1>My Person Form</h1>
<form>
<InputField name="fullName" value={person.fullName} onChange={this.updateProperty}/>
<InputField name="job" value={person.job} onChange={this.updateProperty}/>
<InputField name="email" value={person.email} onChange={this.updateProperty}/>
<PersonAddress address={person.address} />
{
person.tasks
.map((task) => <PersonTask key={task.id} task={task} />)
}
</form>
</div>
)
}
}
import {observable} from 'mobx'
var person = observable({
fullName: 'John Doe',
job: 'Web Developer',
email: 'john.doe@example.com',
address: {
city: 'Budapest',
postalCode: '1000',
street: 'Reactive street'
}
})
updateArray (key, value) {
const array = this.props[formDataProp][key]
const index = array.indexOf(value)
if (array.indexOf(value) > -1) {
array.splice(index, 1)
} else {
array.push(value)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment