Reputation: 25
I have 3 fields in a form: fieldA fieldB fieldC
.
What I want: I want the third field that the user has yet to fill to be a function of the other two. E.g. If you set field fieldA
and fieldB
to 1 and 2 respectively, I want fieldC
to be 1/2. How do I get the this dynamic, dependent field to work?
I am currently using the package FormIK but will accept any answer.
This is my current build:
const MyFieldC = (props) => {
const {
values: { textA, textB },
touched,
setFieldValue,
} = useFormikContext();
const [field, meta] = useField(props);
React.useEffect(() => {
// set the value of textC, based on textA and textB
if (
textA.trim() !== '' &&
textB.trim() !== '' &&
touched.textA &&
touched.textB
) {
setFieldValue(props.name, textA/textB);
}
}, [textB, textA, touched.textA, touched.textB, setFieldValue, props.name]);
return (
<>
<input {...props} {...field} />
{!!meta.touched && !!meta.error && <div>{meta.error}</div>}
</>
);
};
const MyFieldA = (props) => {
const {
values: { textC, textB },
touched,
setFieldValue,
} = useFormikContext();
const [field, meta] = useField(props);
React.useEffect(() => {
// set the value of textC, based on textA and textB
if (
textC.trim() !== '' &&
textB.trim() !== '' &&
touched.textA &&
touched.textB
) {
setFieldValue(props.name, textA/textB);
}
}, [textB, textC, touched.textA, touched.textB, setFieldValue, props.name]);
return (
<>
<input {...props} {...field} />
{!!meta.touched && !!meta.error && <div>{meta.error}</div>}
</>
);
};
const MyFieldB = (props) => {
const {
values: { textA, textC },
touched,
setFieldValue,
} = useFormikContext();
const [field, meta] = useField(props);
React.useEffect(() => {
// set the value of textC, based on textA and textB
if (
textA.trim() !== '' &&
textC.trim() !== '' &&
touched.textA &&
touched.textC
) {
setFieldValue(props.name, textA/textC);
}
}, [textC, textA, touched.textA, touched.textC, setFieldValue, props.name]);
return (
<>
<input {...props} {...field} />
{!!meta.touched && !!meta.error && <div>{meta.error}</div>}
</>
);
};
function Form() {
// Note that we provide initalValues all 3 fields.
const initialValues = { textA: '', textB: '', textC: '' };
return (
<div className="App">
<Formik
initialValues={initialValues}
onSubmit={async (values) => alert(JSON.stringify(values, null, 2))}
>
<div className="section">
<Form>
<label>
FieldA
<MyFieldA name="textA" />
</label>
<label>
FieldB
<MyFieldB name="textB" />
</label>
<label>
FieldC
<MyFieldC name="textC" />
</label>
<button type="submit">Submit</button>
</Form>
</div>
</Formik>
</div>
);
}
If i submit values for 2 of the 3 values, I get the error:
TypeError: textB.trim is not a function
Upvotes: 2
Views: 899
Reputation: 2733
you can use values props and change the value of fieldC.
const initialValues={textA:'',textB :''}
<Formik
initialValues={initialValues}
onSubmit={async (values) => alert(JSON.stringify(values, null, 2))}
>
{({values}) => (
<Form>
<label>
FieldA
<MyFieldA name="textA" />
</label>
<label>
FieldB
<MyFieldB name="textB" />
</label>
<label>
FieldC
<MyFieldC name="textC" value={(values.textA && values.textB )
? (values.textA/values.textB) : ''}/>
</label>
<button type="submit">Submit</button>
</Form>
)}
</Formik>
Upvotes: 1