I am trying to use Material UI's Autocomplete with Formik. Here is a custom Autocomplete component I wrote to use with Formik.
import React from "react";
import Autocomplete from "@material-ui/lab/Autocomplete";
import TextField from "@material-ui/core/TextField";
import { fieldToTextField } from "formik-material-ui";
const FormikAutocomplete = ({ textFieldProps, ...props }) => {
const {
form: { setTouched, setFieldValue },
} = props;
const { error, helperText, ...field } = fieldToTextField(props);
const { name } = field;
return (
<Autocomplete
{...props}
{...field}
onChange={(_, value) =>
setFieldValue(name, value)
}
onBlur={() => setTouched({ [name]: true })}
renderInput={(props) => (
<TextField
{...props}
{...textFieldProps}
helperText={helperText}
error={error}
/>
)}
/>
);
};
export default FormikAutocomplete;
Here is how components callled
<Field
name="title"
component={FormikAutocomplete}
options={gender}
getOptionLabel={(option) => option.title_name_long}
textFieldProps={{
label: "Title",
required: true,
variant: "outlined",
margin: "dense",
}}
/>
Now what I intend to do is: If I have a object like
gender=[{gender_name_short:"F",gender_name_long:"Female},{gender_name_short:"M",gender_name_long:"Male}]
I want the Autocomplete dropdown to show options male,female. But I want the formik state to save M,F respectively once selected from dropdown. Currently the entire object gets saved.
How can this be done?
In FormikAutocomplete
component,
gender_name_long
in getOptionLabel
to display Male
, Female
gender_name_short
in getOptionSelected
to use M
or F
With that, finally, when you submit, you will get to see M
/F
not Male/Female
const gender = [
{ gender_name_short: "F", gender_name_long: "Female" },
{ gender_name_short: "M", gender_name_long: "Male" }
];
const validationSchema = object().shape({
// genderObj: array().required("At least one gender is required")
});
const initialValues = {
username: "abc",
country: "",
gender: "M",
birthdate: null
};
const FormikAutocomplete = ({ textFieldProps, ...props }) => {
const {
form: { setTouched, setFieldValue }
} = props;
const { error, helperText, ...field } = fieldToTextField(props);
const { name } = field;
return (
<Autocomplete
{...field}
{...props}
onChange={(_, data) => {
setFieldValue("gender", data.gender_name_short);
}}
onBlur={() => setTouched({ [name]: true })}
// getOptionLabel={item => item.gender_name_long} //<----see here
getOptionLabel={item => {
// console.log( '====>' , typeof item === "string" ? props.options.find(i => i.gender_name_short === item).gender_name_long : item.gender_name_long)
return typeof item === "string"
? props.options.find(i => i.gender_name_short === item)
.gender_name_long
: item.gender_name_long;
}}
// getOptionLabel={item => typeof item === 'string' ? props.options.find(i => i.gender_name_short === item).gender_name_long : item.gender_name_long}
getOptionSelected={(item, current) => {
return item.gender_name_short === current;
}}
// defaultValue={'hi'}
renderInput={props => (
<TextField
{...props}
{...textFieldProps}
helperText={helperText}
error={error}
/>
)}
/>
);
};
const SimpleFormExample = () => (
<div>
<h1>Simple Form Example</h1>
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
validateOnBlur={false}
validateOnChange
onSubmit={(values, { resetForm, setSubmitting }) => {
console.log(values);
resetForm();
// setSubmitting(false);
}}
>
{formik => (
<Form>
<Field
name="gender"
component={FormikAutocomplete}
label="gender"
options={gender}
textFieldProps={{
fullWidth: true,
margin: "normal",
variant: "outlined"
}}
// multiple
/>
<button type="submit">Submit</button>
</Form>
)}
</Formik>
</div>
);
export default SimpleFormExample;