-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implemented library to create a simple form that can be connected via…
… redux to react
- Loading branch information
1 parent
7271161
commit 129c469
Showing
18 changed files
with
475 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
node_modules | ||
examples/build |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="utf-8"> | ||
<meta content="ie=edge" http-equiv="x-ua-compatible"> | ||
<title>ReactReduxForm</title> | ||
</head> | ||
<body> | ||
<div id="app"></div> | ||
</body> | ||
</html> |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
"use strict"; | ||
|
||
import React from 'react'; | ||
import ReactDOM from 'react-dom'; | ||
import {Provider} from 'react-redux'; | ||
import createStore from '../base/create-store'; | ||
import AuthForm from './auth-form'; | ||
import Layout from './layout'; | ||
|
||
ReactDOM.render( | ||
<Provider store={createStore(AuthForm.reducer)}> | ||
<Layout/> | ||
</Provider>, | ||
document.getElementById('app') | ||
); |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
|
||
import {createForm} from '../../../src/index'; | ||
import {isRequired} from '../base/validator'; | ||
|
||
export default createForm({ | ||
name: 'auth', | ||
selector: state => state, | ||
fields: { | ||
username: { | ||
validators: [isRequired] | ||
}, | ||
password: { | ||
validators: [isRequired] | ||
} | ||
} | ||
}); |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
"use strict"; | ||
|
||
import React, {PureComponent, PropTypes} from 'react'; | ||
import AuthForm from './auth-form'; | ||
import InputField from '../base/input-field'; | ||
import BaseSubmitButton from '../base/submit-button'; | ||
|
||
const UsernameField = AuthForm.connectors.field('username')(InputField); | ||
const PasswordField = AuthForm.connectors.field('password')(InputField); | ||
const SubmitButton = AuthForm.connectors.validator(BaseSubmitButton); | ||
|
||
export default class Layout extends PureComponent { | ||
|
||
constructor(...args) { | ||
super(...args); | ||
this.handleSubmit = this.handleSubmit.bind(this); | ||
} | ||
|
||
handleSubmit() { | ||
alert('hurray'); | ||
} | ||
|
||
render() { | ||
return ( | ||
<form> | ||
<UsernameField id="username" label="Username"/> | ||
<PasswordField type="password" id="password" label="Password"/> | ||
<SubmitButton handleSubmit={this.handleSubmit} label="Submit"/> | ||
</form> | ||
); | ||
} | ||
|
||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
"use strict"; | ||
|
||
import {applyMiddleware, createStore} from 'redux'; | ||
import createLogger from 'redux-logger'; | ||
|
||
export default rootReducer => createStore( | ||
rootReducer, | ||
applyMiddleware(createLogger()) | ||
); |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
"use strict"; | ||
|
||
import React, {PureComponent, PropTypes} from 'react'; | ||
|
||
export default class InputFields extends PureComponent { | ||
|
||
static propTypes = { | ||
id: PropTypes.string.isRequired, | ||
label: PropTypes.string.isRequired, | ||
type: PropTypes.string, | ||
error: PropTypes.string, | ||
active: PropTypes.bool.isRequired, | ||
touched: PropTypes.bool.isRequired, | ||
handleFocus: PropTypes.func.isRequired, | ||
handleBlur: PropTypes.func.isRequired, | ||
handleChange: PropTypes.func.isRequired, | ||
}; | ||
|
||
static defaultProps = { | ||
type: 'text' | ||
}; | ||
|
||
constructor(...args) { | ||
super(...args); | ||
this.handleChange = this.handleChange.bind(this); | ||
} | ||
|
||
handleChange(event) { | ||
event.preventDefault(); | ||
this.props.handleChange(event.target.value); | ||
} | ||
|
||
render() { | ||
const {id, label, error, active, touched, handleFocus, handleBlur, ...rest} = this.props; | ||
delete rest.handleChange; | ||
|
||
let className = 'form-group'; | ||
if (active) { | ||
className += ' active'; | ||
} else if (touched) { | ||
className += error ? ' invalid' : ' valid'; | ||
} | ||
|
||
return ( | ||
<div className={className}> | ||
<label className="control-label" htmlFor={id}>{label}</label> | ||
<input | ||
id={id} | ||
className="form-control" | ||
onFocus={handleFocus} | ||
onBlur={handleBlur} | ||
onChange={this.handleChange} | ||
{...rest} | ||
/> | ||
{error && !active && touched ? <span className="help-block">{error}</span> : null} | ||
</div> | ||
); | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
"use strict"; | ||
|
||
import React, {PureComponent, PropTypes} from 'react'; | ||
|
||
export default class SubmitButton extends PureComponent { | ||
|
||
static propTypes = { | ||
label: PropTypes.string.isRequired, | ||
valid: PropTypes.bool.isRequired, | ||
handleValidate: PropTypes.func.isRequired, | ||
handleSubmit: PropTypes.func.isRequired | ||
}; | ||
|
||
constructor(...args) { | ||
super(...args); | ||
this.handleClick = this.handleClick.bind(this); | ||
} | ||
|
||
handleClick(event) { | ||
event.preventDefault(); | ||
if (this.props.valid) { | ||
this.props.handleSubmit(); | ||
} else { | ||
this.props.handleValidate(); | ||
} | ||
} | ||
|
||
render() { | ||
return ( | ||
<button type="submit" className="btn btn-primary" onClick={this.handleClick}> | ||
{this.props.label} | ||
</button> | ||
); | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
"use strict"; | ||
|
||
export const isRequired = value => !value ? 'This field is required' : undefined; |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
{ | ||
"name": "react-redux-form", | ||
"version": "0.1.0", | ||
"license": "MIT", | ||
"devDependencies": { | ||
"babel-core": "^6.18.2", | ||
"babel-loader": "^6.2.7", | ||
"babel-preset-es2015": "^6.18.0", | ||
"babel-preset-react": "^6.16.0", | ||
"babel-preset-stage-1": "^6.16.0", | ||
"babel-plugin-transform-class-properties": "^6.18.0", | ||
"html-webpack-plugin": "^2.24.1", | ||
"react": "^15.3.2", | ||
"react-dom": "^15.3.2", | ||
"redux-logger": "^2.7.4", | ||
"webpack": "^1.13.3" | ||
}, | ||
"scripts": { | ||
"watch-example-auth": "EXAMPLE=auth webpack --watch", | ||
"build-example-auth": "EXAMPLE=auth webpack" | ||
}, | ||
"dependencies": { | ||
"reselect": "^2.5.4", | ||
"react-redux": "^4.4.5", | ||
"redux": "^3.6.0" | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
"use strict"; | ||
|
||
export const FORM_FOCUS_FIELD = 'FORM_FOCUS_FIELD'; | ||
export const FORM_BLUR_FIELD = 'FORM_BLUR_FIELD'; | ||
export const FORM_CHANGE_FIELD = 'FORM_CHANGE_FIELD'; | ||
export const FORM_LOAD_VALUES = 'FORM_LOAD_VALUES'; | ||
export const FORM_VALIDATE = 'FORM_VALIDATE'; | ||
export const FORM_RESET = 'FORM_RESET'; |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
"use strict"; | ||
|
||
import * as actionTypes from './action-types'; | ||
|
||
export default formType => ({ | ||
focusField: fieldName => ({ | ||
type: actionTypes.FORM_FOCUS_FIELD, | ||
formType, | ||
fieldName | ||
}), | ||
blurField: fieldName => ({ | ||
type: actionTypes.FORM_BLUR_FIELD, | ||
formType, | ||
fieldName | ||
}), | ||
changeField: (fieldName, value) => ({ | ||
type: actionTypes.FORM_CHANGE_FIELD, | ||
formType, | ||
fieldName, | ||
value | ||
}), | ||
loadValues: values => ({ | ||
type: actionTypes.FORM_LOAD_VALUES, | ||
formType, | ||
values | ||
}), | ||
validate: () => ({ | ||
type: actionTypes.FORM_VALIDATE, | ||
formType | ||
}), | ||
reset: () => ({ | ||
type: actionTypes.FORM_RESET, | ||
formType | ||
}) | ||
}); |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
"use strict"; | ||
|
||
import {createStructuredSelector} from 'reselect'; | ||
import {bindActionCreators} from 'redux'; | ||
import {connect} from 'react-redux'; | ||
|
||
const createMapStateToPropsForField = (fieldName, selectors) => createStructuredSelector({ | ||
value: selectors.fieldValueSelector(fieldName), | ||
touched: selectors.fieldTouchedSelector(fieldName), | ||
active: selectors.fieldActiveSelector(fieldName), | ||
error: selectors.fieldErrorSelector(fieldName) | ||
}); | ||
|
||
const createActionCreatorsForField = (fieldName, actionCreators) => ({ | ||
handleFocus: actionCreators.focusField.bind(undefined, fieldName), | ||
handleBlur: actionCreators.blurField.bind(undefined, fieldName), | ||
handleChange: actionCreators.changeField.bind(undefined, fieldName) | ||
}); | ||
|
||
const createMapDispatchToPropsForField = (fieldName, actionCreators) => fieldName ? | ||
createActionCreatorsForField(fieldName, actionCreators) : | ||
(dispatch, ownProps) => bindActionCreators( | ||
createActionCreatorsForField(ownProps.fieldName, actionCreators), | ||
dispatch | ||
); | ||
|
||
const createMapStateToPropsForValidator = selectors => createStructuredSelector({ | ||
valid: selectors.formValidSelector | ||
}); | ||
|
||
const createMapDispatchToPropsForValidator = actionCreators => ({ | ||
handleValidate: actionCreators.validate | ||
}); | ||
|
||
export default (selectors, actionCreators) => ({ | ||
field: fieldName => connect( | ||
createMapStateToPropsForField(fieldName, selectors), | ||
createMapDispatchToPropsForField(fieldName, actionCreators) | ||
), | ||
validator: connect( | ||
createMapStateToPropsForValidator(selectors), | ||
createMapDispatchToPropsForValidator(actionCreators) | ||
) | ||
|
||
}); |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
"use strict"; | ||
|
||
import createSelectors from './create-selectors'; | ||
import createActionCreators from './create-action-creators'; | ||
import createConnectors from './create-connectors'; | ||
import createReducer from './create-reducer'; | ||
|
||
export default formType => { | ||
const selectors = createSelectors(formType); | ||
const actionCreators = createActionCreators(formType); | ||
|
||
return { | ||
selectors, | ||
actionCreators, | ||
connectors: createConnectors(selectors, actionCreators), | ||
reducer: createReducer(formType) | ||
}; | ||
}; |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
"use strict"; | ||
|
||
import * as actions from './action-types'; | ||
|
||
const updateField = (state, fieldName, object) => ({ | ||
...state, | ||
[fieldName]: { | ||
...state[fieldName], | ||
...object | ||
} | ||
}); | ||
|
||
const focusField = (state, action) => updateField(state, action.fieldName, {active: true, touched: true}); | ||
|
||
const blurField = (state, action) => updateField(state, action.fieldName, {active: false, touched: true}); | ||
|
||
const changeField = (state, action) => updateField(state, action.fieldName, {value: action.value, touched: true}); | ||
|
||
const loadValues = (state, action) => Object.keys(action.values).reduce( | ||
(state, fieldName) => { | ||
state[fieldName] = { | ||
...state[fieldName], | ||
value: action.values[fieldName] | ||
}; | ||
|
||
return state; | ||
}, | ||
{...state} | ||
); | ||
|
||
const validate = (state, action) => Object.keys(action.formType.fields).reduce( | ||
(state, fieldName) => { | ||
state[fieldName] = { | ||
...state[fieldName], | ||
touched: true | ||
}; | ||
|
||
return state; | ||
}, | ||
{...state} | ||
); | ||
|
||
const reset = () => ({}); | ||
|
||
const actionMap = { | ||
[actions.FORM_FOCUS_FIELD]: focusField, | ||
[actions.FORM_BLUR_FIELD]: blurField, | ||
[actions.FORM_CHANGE_FIELD]: changeField, | ||
[actions.FORM_LOAD_VALUES]: loadValues, | ||
[actions.FORM_VALIDATE]: validate, | ||
[actions.FORM_RESET]: reset | ||
}; | ||
|
||
export default formType => (state = {}, action) => action.type in actionMap && action.formType.name === formType.name ? | ||
actionMap[action.type](state, action) : state; | ||
|
Oops, something went wrong.