/// import * as React from 'react'; import {Component, PropTypes} from 'react'; import {createStore, combineReducers} from 'redux'; import {reduxForm, reducer as reduxFormReducer, ReduxFormProps} from 'redux-form'; namespace SimpleForm { export const fields = ['firstName', 'lastName', 'email', 'sex', 'favoriteColor', 'employed', 'notes']; class SimpleForm extends Component { static propTypes = { fields: PropTypes.object.isRequired, handleSubmit: PropTypes.func.isRequired, resetForm: PropTypes.func.isRequired, submitting: PropTypes.bool.isRequired }; render() { const { fields: {firstName, lastName, email, sex, favoriteColor, employed, notes}, handleSubmit, resetForm, submitting } = this.props; return ( First Name Last Name Email Sex Male Female Favorite Color Red Green Blue Employed Notes {submitting ? : } Submit Clear Values ); } } const Connected = reduxForm({ form: 'simple', fields })(SimpleForm); } namespace SynchronousValidation { export const fields = ['username', 'email', 'age']; const validate = (values:any) => { const errors:any = {}; if (!values.username) { errors.username = 'Required'; } else if (values.username.length > 15) { errors.username = 'Must be 15 characters or less'; } 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.age) { errors.age = 'Required'; } else if (isNaN(Number(values.age))) { errors.age = 'Must be a number'; } else if (Number(values.age) < 18) { errors.age = 'Sorry, you must be at least 18 years old'; } return errors; }; class SynchronousValidationForm extends Component { static propTypes = { fields: PropTypes.object.isRequired, handleSubmit: PropTypes.func.isRequired, resetForm: PropTypes.func.isRequired, submitting: PropTypes.bool.isRequired }; render() { const {fields: {username, email, age}, resetForm, handleSubmit, submitting} = this.props; return ( Username {username.touched && username.error && {username.error}} Email {email.touched && email.error && {email.error}} Age {age.touched && age.error && {age.error}} {submitting ? : } Submit Clear Values ); } } export const Connected = reduxForm({ form: 'synchronousValidation', fields, validate })(SynchronousValidationForm); } namespace SumbitValidation { export const fields = ['username', 'password']; const submit = (values:any, dispatch:any) => { return new Promise((resolve, reject) => { setTimeout(() => { if (['john', 'paul', 'george', 'ringo'].indexOf(values.username) === -1) { reject({username: 'User does not exist', _error: 'Login failed!'}); } else if (values.password !== 'redux-form') { reject({password: 'Wrong password', _error: 'Login failed!'}); } else { resolve(); } }, 1000); // simulate server latency }); }; class SubmitValidationForm extends Component { static propTypes = { fields: PropTypes.object.isRequired, handleSubmit: PropTypes.func.isRequired, error: PropTypes.string, resetForm: PropTypes.func.isRequired, submitting: PropTypes.bool.isRequired }; render() { const {fields: {username, password}, error, resetForm, handleSubmit, submitting} = this.props; return ( Username {username.touched && username.error && {username.error}} Password {password.touched && password.error && {password.error}} {error && {error}} {submitting ? : } Log In Clear Values ); } } export const Connected = reduxForm({ form: 'submitValidation', fields })(SubmitValidationForm); } namespace InitializingFromState { const LOAD = 'redux-form-examples/account/LOAD'; const loadAccount = (data:any) => ({type: LOAD, data}); export const fields = ['firstName', 'lastName', 'age', 'bio']; const data = { // used to populate "account" reducer when "Load" is clicked firstName: 'John', lastName: 'Doe', age: '42', bio: 'Born to write amazing Redux code.' }; interface Props extends ReduxFormProps { load: Function; } class InitializingFromStateForm extends Component { static propTypes = { fields: PropTypes.object.isRequired, handleSubmit: PropTypes.func.isRequired, load: PropTypes.func.isRequired, submitting: PropTypes.bool.isRequired }; render() { const {fields: {firstName, lastName, age, bio}, handleSubmit, load, submitting} = this.props; return ( load(data)}>Load Account First Name Last Name Age Occupation {submitting ? : } Submit ); } } export const Connected = reduxForm({ form: 'initializing', fields }, (state:any) => ({ // mapStateToProps initialValues: state.account.data // will pull state into form's initialValues }), {load: loadAccount} // mapDispatchToProps (will bind action creator to dispatch) )(InitializingFromStateForm); } namespace NormalizingFormData { const reducer = combineReducers({ // other reducers form: reduxFormReducer.normalize({ normalizing: { // <--- name of the form upper: value => value && value.toUpperCase(), // normalizer for 'upper' field } }) }); const store = createStore(reducer); }