|
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 |
|
> |
|
{/* You can pass custom props to InputComponent. |
|
Original comment: props for that field |
|
*/} |
|
<InputComponent /> |
|
</SingleFieldForm> |
|
<SingleFieldForm |
|
form="autoSavingForm-lastName" |
|
fieldName="lastName" |
|
onChangeSubmit={this.updateField} |
|
validate={this.validateLastName} |
|
initialValues={{ lastName: initialValues.lastName }} |
|
destroyOnUnmount={false} |
|
enableReinitialize |
|
keepDirtyOnReinitialize |
|
> |
|
{/* You can pass custom props to InputComponent. |
|
Original comment: props for that field |
|
*/} |
|
<InputComponent /> |
|
</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> |
|
); |
|
} |
|
} |