Reputation: 543
I am using redux form for a React app I am working on, the redux form version is V.6. I am also using a wizard style form(so after each fieldset is completed the user can click a "proceed to next step" button to fill out the next section of the form). So what I want to happen is that when the user fills out the "shipping and delivery" fieldset, I want the "billing and payment" feildset(the next feildset in the form) to auto fill with the values entered in the "shipping and delivery" fieldset. They both are identical fieldsets.
Unfortunately it seems like I will not be able to use the intialValues prop since the form will already be rendered when the users enters their values into the form. I also run into issues setting values in the redux form manually in the backend as redux form doesn't seem to be a fan of this method. I can set the value manually, but then I can no longer update it with the input field
In hindsight I wish I built the form more like the example wizard form on the redux form webpage where each "feildset" is actually its own form, but as of right now I can't go back and make those changes, so it all needs to stay as one big form.
If anyones has any advice or opinions please let me know!
The form dumbed down looks like this:
<form>
<ShippingAndDelivery
checkFieldsetProgress={this.checkFieldsetProgress}
handleUpdatingDeliveryType={handleUpdatingDeliveryType}
availableShippingTypes={availableShippingTypes}
shippingType={shippingType}
handleShippingRequest={handleShippingRequest}
recieveShippingError={recieveShippingError}
shippingError={shippingError}
/>
<BillingAndPayment
checkFieldsetProgress={this.checkFieldsetProgress}
handlePopulateBillingAddress={handlePopulateBillingAddress}
promoCodeValue={promoCode}
/>
</form>
It is also in an es6 class so i can mess with states and everything if I need to.
The fieldset components(so ShippingAndDelivery and BillingAndPayment) use the and component like this:
class shippingAndDelivery extends React.Component {
render () {
const {
whatEverPropsNeeded
} = this.props;
return (
<div>
<Fields
names={[
'address_shipping',
'email_shipping'
]}
component={RenderedFields}
whatEverPropsNeeded={whatEverPropsNeeded}
/>
</div>
)
}
}
const RenderedFields = ( fields ) => (
<div className={style.container} onChange={fields.updateProgress(fields)}>
<Col md={8}>
<fieldset>
<div className={style.title}>
<p>Shipping Address</p>
</div>
<Col md={12}>
<BasicInput
input={fields.email_shipping.input}
meta={fields.email_shipping.meta}
disabled={false}
placeholder="Email Address"
/>
</Col>
<Col md={12}>
<BasicInput
input={fields.address_shipping.input}
meta={fields.address_shipping.meta}
disabled={false}
placeholder="Address Line 1"
/>
</Col>
</div>
</fieldset>
</div>
);
Upvotes: 3
Views: 2286
Reputation: 18556
You can use the enableReinitialize
prop of reduxForm
to re-initialize the form any time initialValues
changes, thus enabling you populate the downstream fields with values from the upstream.
I would use formValueSelector
to extract the values from the redux store and set them to initialValues
. Use the keepDirtyOnReinitialize
prop to make sure reinitialization does not overwrite your unsaved changes to the shipping address. Example:
const selector = formValueSelector('MyFormName')
const mapStateToProps = reducers => {
// obtain shipping address values from the redux store
const {
address,
addressOptional,
city,
zipCode,
country
} = selector(reducers, 'shipping')
return {
initialValues: {
// shipping address is empty initially
shipping: {
address: '',
addressOptional: '',
city: '',
zipCode: '',
country: ''
},
// billing address initial values are changed any time
// the shipping address values are changed
billing: {
address,
addressOptional,
city,
zipCode,
country
}
}
}
}
@connect(mapStateToProps)
@reduxForm({
form: 'MyFormName',
// reinitialize the form every time initialValues change
enableReinitialize: true,
// make sure dirty fields (those the user has already edited)
// are not overwritten by reinitialization
keepDirtyOnReinitialize: true
})
class MyFormContainer extends MyFormComponent {}
Hope this helps!
Upvotes: 3