Reputation: 105
I use Autocomplete from @Mui. I made this component
const Profile = () => {
const {
register,
handleSubmit,
setValue,
formState: { errors },
} = useForm({});
const [countries, setCountries] = useState([]);
const submit = async (value) => {
console.log(value);
console.log(value.countries);
};
useEffect(() => {
axios.get("get-countries").then((data) => {
setCountries(data.data);
});
}, []);
return (
<>
<form method="post" onSubmit={handleSubmit(submit)}>
{categories.countries && (
<Autocomplete
id="country-select-demo"
options={categories.countries}
autoHighlight
getOptionLabel={(option) => option.country}
renderOption={(props, option) => (
<Box
component="li"
sx={{ "& > img": { mr: 2, flexShrink: 0 } }}
{...props}
>
<img
loading="lazy"
width="20"
src={`https://flagcdn.com/w20/${option.symbol.toLowerCase()}.png`}
srcSet={`https://flagcdn.com/w40/${option.symbol.toLowerCase()}.png 2x`}
alt=""
/>
{option.country}
</Box>
)}
renderInput={(params) => (
<TextField
{...params}
label="Country"
inputProps={{
...params.inputProps,
autoComplete: "country",
}}
{...register("country", {
required: true,
})}
/>
)}
onChange={(e, value) => setValue("country", value?.id)}
/>
)}
<Button variant="contained" type="submit" sx={{ marginTop: 3 }}>
Submit
</Button>
</form>
</>
);
};
Problem is that I need to return after submit in console.log id of country but it return country. Backend return json which looks like this: {"id":1,"country":"United Kingdom","symbol":"uk"}
. You can see that I tryed using onChange in order to change defaul value but it doesn't work. I can use hook useState but I use react-hooks-form są it doesn't matter. I need to use register and return id from Autoselect.
How can I return id instead of country?
@Edit
I may not have explained everything thoroughly. I have a problem with the Autocomplete component. With normal select, I can add a custom value to each option, such as.
<select>
<option value="1">United Kingdom</option>
</select>
But I don't know is to do similarly in the case of this component
Upvotes: 3
Views: 340
Reputation: 1635
This link displays a diff showing the only changes needed to get the code working. With these changes in place, the console.log
output displays an object with the id
property. The complete, updated version of the function is copied below.
A live demo (without the country flags) is available.
The problem was more related to react-hook-form than to MUI Autocomplete.
The MUI docs say this about getOptionLabel:
Used to determine the string value for a given option. It's used to fill the input (and the list box options if renderOption is not provided).
The return values from getOptionLabel (a callback function) populate the value property of the native HTML <input>
element. When a form is submitted react-hook-form reads data from the value property of the form's fields. In the code, getOptionLabel returns the country name, this is what is read (and returned upon form submission) by react-hook-form. This is the default behaviour when form fields are registered using the react-hook-form register function.
The important change needed to the code is to avoid registering the element with react-hook-form. This allows us to avoid default behavior. Since, id
is desired, not the country name, we need to use the react-hook-form setValue function to switch from using the default <input>
value property to id
.
The react-hook-form docs say:
It's recommended to register the input's name before invoking setValue.
However:
you can setValue to a unregistered input.
const Profile = () => {
const {
register,
handleSubmit,
setValue,
formState: { errors },
} = useForm({});
const [countries, setCountries] = useState([]);
const submit = async (value) => {
console.log(value);
console.log(value.countries);
};
useEffect(() => {
axios.get("get-countries").then((data) => {
setCountries(data.data);
});
}, []);
return (
<>
<form method="post" onSubmit={handleSubmit(submit)}>
{countries && (
<Autocomplete
id="country-select-demo"
options={countries}
autoHighlight
getOptionLabel={(option) => option.country}
renderOption={(props, option) => (
<Box
component="li"
sx={{ "& > img": { mr: 2, flexShrink: 0 } }}
{...props}
>
<img
loading="lazy"
width="20"
src={`https://flagcdn.com/w20/${option.symbol.toLowerCase()}.png`}
srcSet={`https://flagcdn.com/w40/${option.symbol.toLowerCase()}.png 2x`}
alt=""
/>
{option.country}
</Box>
)}
renderInput={(params) => (
<TextField
{...params}
label="Country"
inputProps={{
...params.inputProps,
autoComplete: "country",
}}
/>
)}
onChange={(e, value) => setValue("id", value?.id)}
/>
)}
<Button variant="contained" type="submit" sx={{ marginTop: 3 }}>
Submit
</Button>
</form>
</>
);
};
Upvotes: 0