The original example: Redux Form - Wizard Form Example
Last active
October 31, 2017 14:24
-
-
Save shinaisan/9b549dd595c8b766ecf5accaab7d61de to your computer and use it in GitHub Desktop.
Redux Form - Wizard Form Example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import WizardForm from './WizardForm'; | |
import { createStore } from 'redux'; | |
import { Provider } from 'react-redux'; | |
import reducer from './reducer'; | |
import "bootstrap/dist/css/bootstrap.css"; | |
const store = createStore(reducer); | |
class App extends React.Component { | |
constructor(props) { | |
super(props); | |
this.state = {debug: ''}; | |
} | |
handleSubmit(values) { | |
const self = this; | |
self.setState({debug: JSON.stringify(values)}); | |
} | |
render() { | |
const onSubmit = this.handleSubmit.bind(this); | |
return ( | |
<Provider store={store}> | |
<div> | |
<WizardForm onSubmit={onSubmit} /> | |
<div> | |
<pre>{this.state.debug}</pre> | |
</div> | |
</div> | |
</Provider> | |
); | |
} | |
} | |
export default App; | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
NAME=redux-form-wizard | |
echo -n "This script runs create-react-app $NAME. Proceed? (Y/N) " | |
read YN | |
if [ x$YN != xY ] | |
then | |
echo "Bye." | |
exit | |
fi | |
# Delete this line only if you are sure what is done from this line on. | |
exit | |
create-react-app $NAME | |
cd $NAME | |
cp -v ../package.json . | |
cd src | |
rm -f App.* logo.svg | |
cp -v ../../*.js . | |
cd .. | |
yarn install | |
echo 'To launch the dev server, run `yarn run start`.' | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "redux-form-selecting-form-values", | |
"version": "0.1.0", | |
"private": true, | |
"dependencies": { | |
"bootstrap": "^3.3.7", | |
"immutable": "^3.8.2", | |
"react": "^16.0.0", | |
"react-bootstrap": "^0.31.5", | |
"react-dom": "^16.0.0", | |
"react-redux": "^5.0.6", | |
"redux": "^3.7.2", | |
"redux-form": "^7.1.2", | |
"redux-immutablejs": "^0.0.8" | |
}, | |
"devDependencies": { | |
"react-scripts": "1.0.14" | |
}, | |
"scripts": { | |
"start": "react-scripts start", | |
"build": "react-scripts build", | |
"test": "react-scripts test --env=jsdom", | |
"eject": "react-scripts eject" | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { combineReducers } from 'redux'; | |
import { reducer as formReducer } from 'redux-form'; | |
const rootReducer = combineReducers({ | |
form: formReducer | |
}); | |
export default rootReducer; | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react' | |
const renderField = ({ input, label, type, meta: { touched, error } }) => ( | |
<div> | |
<label>{label}</label> | |
<div> | |
<input {...input} placeholder={label} type={type} /> | |
{touched && error && <span>{error}</span>} | |
</div> | |
</div> | |
) | |
export default renderField |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const validate = values => { | |
const errors = {} | |
if (!values.firstName) { | |
errors.firstName = 'Required' | |
} | |
if (!values.lastName) { | |
errors.lastName = 'Required' | |
} | |
if (!values.email) { | |
errors.email = 'Required' | |
} else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) { | |
errors.email = 'Invalid email address' | |
} | |
if (!values.sex) { | |
errors.sex = 'Required' | |
} | |
if (!values.favoriteColor) { | |
errors.favoriteColor = 'Required' | |
} | |
return errors | |
} | |
export default validate |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const warn = values => { | |
// IMPORTANT: values is an Immutable.Map here! | |
const errors = {} | |
if (values.get('username') && /[^a-zA-Z0-9 ]/i.test(values.get('username'))) { | |
errors.username = 'Only alphanumeric characters' | |
} | |
if (values.get('email') && /.+@aol\.com/.test(values.get('email'))) { | |
errors.email = 'Really? You still use AOL for your email?' | |
} | |
if (values.get('age') && values.get('age') > 65) { | |
errors.age = 'You might be too old for this' | |
} | |
return errors | |
} | |
export default warn |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { Component } from 'react' | |
import PropTypes from 'prop-types' | |
import WizardFormFirstPage from './WizardFormFirstPage' | |
import WizardFormSecondPage from './WizardFormSecondPage' | |
import WizardFormThirdPage from './WizardFormThirdPage' | |
class WizardForm extends Component { | |
constructor(props) { | |
super(props) | |
this.nextPage = this.nextPage.bind(this) | |
this.previousPage = this.previousPage.bind(this) | |
this.state = { | |
page: 1 | |
} | |
} | |
nextPage() { | |
this.setState({ page: this.state.page + 1 }) | |
} | |
previousPage() { | |
this.setState({ page: this.state.page - 1 }) | |
} | |
render() { | |
const { onSubmit } = this.props | |
const { page } = this.state | |
return ( | |
<div> | |
{page === 1 && <WizardFormFirstPage onSubmit={this.nextPage} />} | |
{page === 2 && ( | |
<WizardFormSecondPage | |
previousPage={this.previousPage} | |
onSubmit={this.nextPage} | |
/> | |
)} | |
{page === 3 && ( | |
<WizardFormThirdPage | |
previousPage={this.previousPage} | |
onSubmit={onSubmit} | |
/> | |
)} | |
</div> | |
) | |
} | |
} | |
WizardForm.propTypes = { | |
onSubmit: PropTypes.func.isRequired | |
} | |
export default WizardForm |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react' | |
import { Field, reduxForm } from 'redux-form' | |
import validate from './validate' | |
import renderField from './renderField' | |
import { | |
Form, | |
Button | |
} from 'react-bootstrap' | |
const WizardFormFirstPage = props => { | |
const { handleSubmit } = props | |
return ( | |
<Form onSubmit={handleSubmit}> | |
<Field | |
name="firstName" | |
type="text" | |
component={renderField} | |
label="First Name" | |
/> | |
<Field | |
name="lastName" | |
type="text" | |
component={renderField} | |
label="Last Name" | |
/> | |
<div> | |
<Button type="submit" bsStyle="primary" className="next"> | |
Next | |
</Button> | |
</div> | |
</Form> | |
) | |
} | |
export default reduxForm({ | |
form: 'wizard', // <------ same form name | |
destroyOnUnmount: false, // <------ preserve form data | |
forceUnregisterOnUnmount: true, // <------ unregister fields on unmount | |
validate | |
})(WizardFormFirstPage) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react' | |
import { Field, reduxForm } from 'redux-form' | |
import validate from './validate' | |
import renderField from './renderField' | |
import { | |
Form, FormGroup, | |
Button | |
} from 'react-bootstrap' | |
const renderError = ({ meta: { touched, error } }) => | |
touched && error ? <span>{error}</span> : false | |
const WizardFormSecondPage = props => { | |
const { handleSubmit, previousPage } = props | |
return ( | |
<Form onSubmit={handleSubmit}> | |
<Field name="email" type="email" component={renderField} label="Email" /> | |
<FormGroup> | |
<label>Sex</label> | |
<div> | |
<label> | |
<Field | |
name="sex" | |
component="input" | |
type="radio" | |
value="male" | |
/>{' '} | |
Male | |
</label> | |
<label> | |
<Field | |
name="sex" | |
component="input" | |
type="radio" | |
value="female" | |
/>{' '} | |
Female | |
</label> | |
<Field name="sex" component={renderError} /> | |
</div> | |
</FormGroup> | |
<div> | |
<Button type="button" | |
bsStyle="default" className="previous" onClick={previousPage}> | |
Previous | |
</Button> | |
<Button type="submit" | |
bsStyle="primary" className="next"> | |
Next | |
</Button> | |
</div> | |
</Form> | |
) | |
} | |
export default reduxForm({ | |
form: 'wizard', //Form name is same | |
destroyOnUnmount: false, | |
forceUnregisterOnUnmount: true, // <------ unregister fields on unmount | |
validate | |
})(WizardFormSecondPage) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react' | |
import { Field, reduxForm } from 'redux-form' | |
import validate from './validate' | |
import { | |
Form, FormGroup, | |
Button | |
} from 'react-bootstrap' | |
const colors = ['Red', 'Orange', 'Yellow', 'Green', 'Blue', 'Indigo', 'Violet'] | |
const renderColorSelector = ({ input, meta: { touched, error } }) => ( | |
<div> | |
<select {...input}> | |
<option value="">Select a color...</option> | |
{colors.map(val => ( | |
<option value={val} key={val}> | |
{val} | |
</option> | |
))} | |
</select> | |
{touched && error && <span>{error}</span>} | |
</div> | |
) | |
const WizardFormThirdPage = props => { | |
const { handleSubmit, pristine, previousPage, submitting } = props | |
return ( | |
<Form onSubmit={handleSubmit}> | |
<FormGroup> | |
<label>Favorite Color</label> | |
<Field name="favoriteColor" component={renderColorSelector} /> | |
</FormGroup> | |
<FormGroup> | |
<label htmlFor="employed">Employed</label> | |
<div> | |
<Field | |
name="employed" | |
id="employed" | |
component="input" | |
type="checkbox" | |
/> | |
</div> | |
</FormGroup> | |
<FormGroup> | |
<label>Notes</label> | |
<div> | |
<Field name="notes" component="textarea" placeholder="Notes" /> | |
</div> | |
</FormGroup> | |
<div> | |
<Button type="button" bsStyle="default" | |
className="previous" onClick={previousPage}> | |
Previous | |
</Button> | |
<Button type="submit" bsStyle="primary" | |
disabled={pristine || submitting}> | |
Submit | |
</Button> | |
</div> | |
</Form> | |
) | |
} | |
export default reduxForm({ | |
form: 'wizard', //Form name is same | |
destroyOnUnmount: false, | |
forceUnregisterOnUnmount: true, // <------ unregister fields on unmount | |
validate | |
})(WizardFormThirdPage) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment