like-gold
like-gold2mo ago

Programmatically update value of Autocomplete

Hello, I am using useAutocomplete which is working great so far but I am trying to implement an additional scenario which involves updating the autocomplete value programmatically. The problem I am having at the moment is that the UI of the autoccomplete is not updated when I use the setValue method of the form. If I am explicitly setting the value property of the autocomplete everything works but I am wondering if there is a better way to handle this so that I do not have to add an additional state to my component. Here is the definition of my autocomplete:
const { autocompleteProps } = useAutocomplete<ICasinoTag>({
resource: "casino/tags",
dataProviderName: "api",
debounce: 500,
searchField: "name"
});
const { autocompleteProps } = useAutocomplete<ICasinoTag>({
resource: "casino/tags",
dataProviderName: "api",
debounce: 500,
searchField: "name"
});
<Controller
control={control}
name="tags"
rules={{ required: "This field is required" }}
render={({ field }) => {
return (
<Autocomplete
{...autocompleteProps}
multiple
onChange={(_, value) => {
field.onChange(value);
}}
sx={{ width: '100%' }}
getOptionLabel={tag => tag.name}
isOptionEqualToValue={(option, value) =>
value === undefined ||
option?.id?.toString() === (value?.id ?? value)?.toString()
}
renderInput={(params) => {
return (
<TextField
{...params}
label="Tags"
margin="normal"
variant="outlined"
error={!!errors.tags}

required
placeholder="Select tags"
/>
);
}
}
/>
);
}
}
/>
<Controller
control={control}
name="tags"
rules={{ required: "This field is required" }}
render={({ field }) => {
return (
<Autocomplete
{...autocompleteProps}
multiple
onChange={(_, value) => {
field.onChange(value);
}}
sx={{ width: '100%' }}
getOptionLabel={tag => tag.name}
isOptionEqualToValue={(option, value) =>
value === undefined ||
option?.id?.toString() === (value?.id ?? value)?.toString()
}
renderInput={(params) => {
return (
<TextField
{...params}
label="Tags"
margin="normal"
variant="outlined"
error={!!errors.tags}

required
placeholder="Select tags"
/>
);
}
}
/>
);
}
}
/>
5 Replies
kapa.ai
kapa.ai2mo ago
Hi @Milan Nankov. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- The Material UI Autocomplete component has two manageable states: the value state and the input value. The value state represents the value chosen by the user by clicking or pressing “Enter.” The input value represents the value displayed in the textbox. In your case, you are using the Controller component from react-hook-form to wrap your Autocomplete component. The Controller component takes care of the registration process and updates the value prop of the Autocomplete component. When you want to programmatically update the value of the Autocomplete component, you should use the setValue method from react-hook-form. This method allows you to programmatically set the value of the field. Here is an example of how you can use the setValue method:
const { control, setValue } = useForm();

// ...

<Controller
control={control}
name="tags"
rules={{ required: "This field is required" }}
render={({ field }) => {
return (
<Autocomplete
{...autocompleteProps}
multiple
onChange={(_, value) => {
field.onChange(value);
setValue("tags", value); // programmatically set the value
}}
// ...
/>
);
}}
/>
const { control, setValue } = useForm();

// ...

<Controller
control={control}
name="tags"
rules={{ required: "This field is required" }}
render={({ field }) => {
return (
<Autocomplete
{...autocompleteProps}
multiple
onChange={(_, value) => {
field.onChange(value);
setValue("tags", value); // programmatically set the value
}}
// ...
/>
);
}}
/>
In this example, the setValue method is called inside the onChange handler of the Autocomplete component. This will ensure that the value of the Autocomplete component is updated both in the UI and in the form state. Please note that the setValue method should be called with the name of the field ("tags" in this case) and the new value. For more information, please refer to the Material UI Autocomplete State Management (https://refine.dev/blog/material-ui-autocomplete-component#material-ui-autocomplete-state-management) section in the Refine documentation. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2mo ago
<@1153414607545839696> kapa.ai is still learning and improving, please let us know how it did by reacting below
like-gold
like-gold2mo ago
@kapa.ai I forgot to share the code that is actually using setValue. Here it is, but after calling it, the UI of the autocomplete is not reflective of the new value.
const onSubmitTagsDialog = (newSelected: ISelectedTag[]) => {
setTagsDialogOpen(false);
// here I am setting the new autocomplete value
setValue("tags", newSelected);
};
const onSubmitTagsDialog = (newSelected: ISelectedTag[]) => {
setTagsDialogOpen(false);
// here I am setting the new autocomplete value
setValue("tags", newSelected);
};
kapa.ai
kapa.ai2mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- The setValue method from react-hook-form should indeed update the value of the field and cause a re-render of the component, which should update the UI. However, the Autocomplete component from Material UI also maintains its own internal state, which might not be updated when you call setValue. To ensure that the Autocomplete component updates its UI, you can try to control its value directly. This can be done by passing the current value from your form state to the value prop of the Autocomplete component. Here is an example of how you can do this:
const { control, setValue, watch } = useForm();
const currentTags = watch("tags");

// ...

<Controller
control={control}
name="tags"
rules={{ required: "This field is required" }}
render={({ field }) => (
<Autocomplete
{...autocompleteProps}
multiple
value={currentTags} // control the value directly
onChange={(_, value) => {
field.onChange(value);
setValue("tags", value); // programmatically set the value
}}
// ...
/>
)}
/>
const { control, setValue, watch } = useForm();
const currentTags = watch("tags");

// ...

<Controller
control={control}
name="tags"
rules={{ required: "This field is required" }}
render={({ field }) => (
<Autocomplete
{...autocompleteProps}
multiple
value={currentTags} // control the value directly
onChange={(_, value) => {
field.onChange(value);
setValue("tags", value); // programmatically set the value
}}
// ...
/>
)}
/>
In this example, the watch function from react-hook-form is used to get the current value of the "tags" field. This value is then passed to the value prop of the Autocomplete component, effectively controlling its value directly. When you call setValue("tags", newSelected), the Autocomplete component should now update its UI to reflect the new value. For more information, please refer to the Material UI Autocomplete State Management (https://refine.dev/blog/material-ui-autocomplete-component#material-ui-autocomplete-state-management) section in the Refine documentation. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2mo ago
<@1153414607545839696> kapa.ai is still learning and improving, please let us know how it did by reacting below