|
export default class BasicMemberDetails extends Component { |
|
|
|
static propTypes = { |
|
/* |
|
... Regular props |
|
formState: connects to Redux state |
|
and aggregates all the 'SingleFieldForm' in one prop. |
|
Look at selector.js below for how. |
|
*/ |
|
|
|
formState: PropTypes.object |
|
}; |
|
|
|
|
|
updateField = (values, dispatch, props) => { |
|
//console.log("Prop Valid:", props.valid, "Prop Dirty:", props.dirty); |
|
if (props.valid && props.dirty && !props.submitting) { |
|
const fieldName = props.form.split('-')[1]; |
|
const actionCreator = this.props.actions[`update${upperFirst(fieldName)}`]; |
|
|
|
return actionCreator( |
|
props.initialValues[fieldName], |
|
values[fieldName], |
|
this.props.loggedInUser.handle |
|
) |
|
.catch((response) => { |
|
const error = response.body && response.body[fieldName]; |
|
console.log('the error is ', error); |
|
const errorObj = { |
|
_error: `There is an error with the ${props.displayName} that you've entered.` |
|
}; |
|
errorObj[fieldName] = error; |
|
throw new SubmissionError(errorObj); |
|
}); |
|
|
|
} |
|
}; |
|
|
|
|
|
validateFirstName = (values, props) => { |
|
const errors = {}; |
|
if (values && (hasNothing(values.firstName) || !isString(values.firstName)) ) { |
|
errors.firstName = ["cannot be blank."]; |
|
} |
|
return errors; |
|
}; |
|
|
|
validateLastName = (values, props) => { |
|
const errors = {}; |
|
if (values && values.lastName && !isString(values.lastName)) { |
|
errors.lastName = ["doesn't seem to be valid."]; |
|
} |
|
return errors; |
|
}; |
|
|
|
/* Similarly, you need a validate function for each 'SingleFieldForm' */ |
|
|
|
render() { |
|
const { actions, loggedInUser, formState, overallSubmitFunction } = this.props; |
|
const userInfo = loggedInUser.info; |
|
|
|
const initialValues = { |
|
firstName: userInfo.first_name, |
|
lastName: userInfo.last_name |
|
}; |
|
|
|
/* |
|
Compute submitting state using |
|
all the flags you might have in Redux, |
|
for eg: when making XHR calls |
|
*/ |
|
const submitting = some( |
|
[ |
|
loggedInUser.updatingFirstName, |
|
loggedInUser.updatingLastName |
|
], |
|
Boolean |
|
); |
|
|
|
/* |
|
This function is critical - it replicates basic Redux-Form functionality |
|
to determine if any of the little forms are submitting or have error. |
|
*/ |
|
const canMoveToNextStep = hasSomething(formState) && !submitting && every( |
|
formState, |
|
(formDetails, formName) => { |
|
const fieldName = formName.split('-')[1]; |
|
const { initial, values, syncErrors, submitSucceeded } = formDetails; |
|
|
|
const isDirty = initial[fieldName] != values[fieldName]; |
|
return (isDirty && submitSucceeded) || (!isDirty && !syncErrors); |
|
} |
|
); |
|
console.log("canMoveToNextStep? ", canMoveToNextStep); |
|
|
|
/* This function computes which field have errors, and then returns an error message */ |
|
const errorMsg = () => { |
|
const errorList = reduce( |
|
formState, |
|
(result, formDetails, formName) => { |
|
/* SingleFieldForm names used a naming convention for simplicity */ |
|
const fieldName = formName.split('-')[1]; |
|
const { error, syncErrors } = formDetails; |
|
|
|
if (isntEmptyString(error)) { |
|
result[fieldName] = error; |
|
|
|
} else if (syncErrors && hasSomething(syncErrors[fieldName])) { |
|
result[fieldName] = syncErrors[fieldName][0]; |
|
|
|
} |
|
|
|
return result; |
|
}, |
|
{} |
|
); |
|
|
|
const fieldsWithError = Object.keys(errorList); |
|
|
|
return 'Some error message that you construct using the information computed in this function'. |
|
}; |
|
|
|
|
|
return ( |
|
<div className = {styles.autoSavingForm}> |
|
<h3>This is an auto-saving form</h3> |
|
<SingleFieldForm |
|
form = "autoSavingForm-firstName" |
|
fieldName = "firstName" |
|
onChangeSubmit = {this.updateField} |
|
validate = {this.validateFirstName} |
|
initialValues = {{ firstName: initialValues.firstName }} |
|
|
|
destroyOnUnmount = {false} |
|
enableReinitialize |
|
keepDirtyOnReinitialize |
|
autoFocus |
|
> |
|
<InputComponent {/* props for that field */} /> |
|
</SingleFieldForm> |
|
<SingleFieldForm |
|
form = "autoSavingForm-lastName" |
|
fieldName = "lastName" |
|
onChangeSubmit = {this.updateField} |
|
validate = {this.validateLastName} |
|
initialValues = {{ lastName: initialValues.lastName }} |
|
|
|
destroyOnUnmount = {false} |
|
enableReinitialize |
|
keepDirtyOnReinitialize |
|
> |
|
<InputComponent {/* props for that field */} /> |
|
</SingleFieldForm> |
|
{/*Example of a non-form component in this component */} |
|
<ReactSuperSelect |
|
controlId = "someId" |
|
name = "someName" |
|
dataSource = {someList} |
|
clearable = {false} |
|
onChange = {this.someOnChangeFunction} |
|
/> |
|
{/*Only need the line below if you want to show form level error */} |
|
<FormError errorMsg = {errorMsg()} /> |
|
<Button |
|
ref = "autoSavingFormButton" |
|
label = {submitting ? "Saving" : "Next!" } |
|
submitting = {submitting} |
|
type = {canMoveToNextStep ? "submit" : "disabled"} |
|
onClick = {overallSubmitFunction} |
|
/> |
|
</div> |
|
); |
|
|
|
} |
|
} |