I need to change the value in my form fields every time a state (called selectedProduct, its input field is not included in Formik tag) changes. I tried:
- putting the value I want in the initialValues (does not work obviously because at the first render I haven't choosen my selectedProduct yet)
- putting the value I want in the "value" props in every field in formik. It almost work: Datepicker gets the right value, select box input does not get any value(idk why), text field take the right value but this is covered by the label. And that's because none of the fields get validated.
This is what I've done, with the two points above applied
import React, { useState } from 'react';
import * as Yup from 'yup';
import {
Formik, Form, ErrorMessage, Field,
} from 'formik';
import {
Button, TextField,
MenuItem,
} from '@material-ui/core';
import DateFnsUtils from '@date-io/date-fns';
import {
MuiPickersUtilsProvider,
KeyboardDatePicker,
} from '@material-ui/pickers';
const validationSchema = Yup.object().shape({
startValidityDate: Yup.date().required(),
discount: Yup.string().required(),
days: Yup.string().required(),
});
const MyComponent = ({filteredProduct, daysList}) => {
const [selectedProduct, setSelectedProduct] = useState('');
const onChangeProduct = (product) => {
setSelectedProduct(product.target.value);
};
const handleRunButton = (newExecution) => {
console.log(newExecution);
};
return (
<div>
<div className={classes.productComboWrapper}>
<div id="selectBoxNotIncludedInFormik">
<TextField
margin="normal"
style={{}}
variant="outlined"
name="productId"
id="productId"
fullWidth
select
label="Select product"
value={selectedProduct?.id}
onChange={(product) => onChangeProduct(product)}
>
<MenuItem key="" value="">
{StringsConst.noneSelected}
</MenuItem>
{filteredProduct?.map((el) => (
<MenuItem key={el} value={el}>
{el.isin}
</MenuItem>
))}
</TextField>
</div>
</div>
<Formik
initialValues={{
startValidityDate: selectedProduct?.startValidityDate,
days: selectedProduct?.coupon?.days,
discount: selectedProduct?.discount,
}}
validationSchema={validationSchema}
onSubmit={(values) => {
const newExecution = {
startValidityDate: values.startValidityDate,
days: values.days,
discount: values.discount,
};
handleRunButton(newExecution);
}}
>
{({
errors, dirty, setFieldValue, values,
}) => (
<Form>
<div className={classes.datePicker}>
<MuiPickersUtilsProvider utils={DateFnsUtils}>
<KeyboardDatePicker
disableToolbar
label="Start Validity Date"
inputVariant="outlined"
variant="inline"
autoOk
fullWidth
disabled
format="dd/MM/yyyy"
value={selectedProduct?.startValidityDate}
onChange={(dt) => setFieldValue('startValidityDate', dt)}
KeyboardButtonProps={{
'aria-label': 'change date',
}}
/>
</MuiPickersUtilsProvider>
</div>
<div className={classes.fieldWrapper}>
<Field
className={classes.field}
name="discount"
as={TextField}
variant="outlined"
margin="normal"
fullWidth
id="discount"
autoComplete="discount"
placeholder="Discount"
disabled
value={selectedProduct?.discount}
/>
</div>
<div className={classes.textFieldWrapper}>
<TextField
margin="normal"
style={{}}
variant="outlined"
name="days"
id="days"
fullWidth
select
label="Days"
disabled
value={selectedProduct?.coupon?.days}
onChange={(val) => setFieldValue('days', val.target.value)}
>
<MenuItem key="" value="">
{StringsConst.noneSelected}
</MenuItem>
{daysList.map((el) => (
<MenuItem key={el} value={el}>
{el}
</MenuItem>
))}
</TextField>
</div>
<div className={classes.buttonContainer}>
<Button
type="submit"
fullWidth
variant="contained"
color="primary"
className={classes.submit}
>
{StringsConst.Run}
</Button>
</div>
</Form>
)}
</Formik>
</div>
)
}
So, the three input fields in the form are disabled, but I need them to fill when I choose a value in the first select box outside of the form. Can you suggest me another approach?