I have a Mui Autocomplete Component with a react-hook-form Controller.
When I set the freeSolo attribute the value doesn't get reset. When I call for example: resetField("selBinvrk") without freeSolo everything works as expected. Here is the code for my autocomplete and the submit function. Can anybody help me with that problem?
<Controller
name={name}
control={control}
rules={rules}
render={({ field: { onChange, value } }) => (
<Autocomplete
disabled={!disabled ? false : true}
value={value}
freeSolo={freeSolo}
//autoSelect={autoSelect}
options={options}
getOptionLabel={getOptionLabel}
isOptionEqualToValue={isOptionEqualToValue}
/* getOptionSelected={(option, value) => {
console.log('get option selected: ', option, value);
return value === undefined || value === "" || option.ID === value.ID}
} */
//console.log(item);
onChange={(event, item) => {
//console.log(item);
onChange(item);
}}
//renderOption={renderOption}
renderInput={(params) => (
<TextField
{...params}
label={label}
variant="outlined"
error={isError}
helperText={errorMessage}
sx={sx}
inputRef={inputRef}
/>
)}
/>
)}
/>
const onSubmit = (data, e) => {
console.log("hä: ", e);
resetField("selBinvrk");
resetField("selMenge");
mutate({
binv_id: data.selBinv.ID,
bsa_id: data.selBinvrk?.BSA_ID || 0,
binvrk_id: data.selBinvrk?.ID || 0,
selMenge: data.selMenge,
bsm_id: data.selBsm.ID,
});
//recaptchaRef.current.execute();
//mutate(data);
};
Related
mui autocomplete wont complete the text letter by letter by order its a bit of a mess , someone got a better autocomplete? or knows how to fix ? (example typing "l" will find first "agropoli" than "london")
<Autocomplete
id="free-solo-demo"
freeSolo
options={cityUniqe}
onChange={(event, value) => setSearch(value)}
renderInput={(params) => (
<TextField
{...params}
error={weatherData?.error ? true : false}
fullWidth
label="name your city here..."
value={search}
onChange={(e) => {
setSearch(e.target.value);
}}
ref={inputField}
onKeyDown={(e) => e.key === "Enter" && handleSubmit(e)}
/>
)}
/>
you need to kinda play with the filtration that happens under the hood, Mui provides a createFilterOptions method which you can use as follows:
import { Autocomplete, TextField, createFilterOptions } from "#mui/material";
export default function App() {
// create your filer options here
const filterOptions = createFilterOptions({
matchFrom: "start",
stringify: (option) => option
});
return (
<Autocomplete
id="free-solo-demo"
freeSolo
options={["agropoli", "london", "parlament"]}
filterOptions={filterOptions} // use them here
onChange={(event, value) => setSearch(value)}
renderInput={(params) => (
<TextField
{...params}
error={weatherData?.error ? true : false}
fullWidth
label="name your city here..."
value={search}
onChange={(e) => {
setSearch(e.target.value);
}}
ref={inputField}
onKeyDown={(e) => e.key === "Enter" && handleSubmit(e)}
/>
)}
/>
);
}
I use material UI autocomplete to create a single-select dropdown.
But the problem is that when I click the close button placed right-side of the input, the onChange event didn't call and my state didn't update.
While in the multi-select mode this event successfully occurred.
Someone helps me to use the remove event in single-select mode.
This is my single select:
<Autocomplete<Option<T>>
onChange={(e: any, newValue) => {
if (newValue) {
handleChangeValue(newValue.value);
}
}}
sx={{ ...sx }}
id={id}
options={options}
isOptionEqualToValue={(newValue, option) =>
newValue.value === option.value
}
defaultValue={
defaultValue && {
value: defaultValue,
label: options.find((option) => option.value === defaultValue)?.label,
}
}
value={
value && {
value: value,
label: options.find((option) => option.value === value)?.label,
}
}
getOptionLabel={(option) => option.label || `${option.value}`}
renderOption={(props, option, { selected }) => (
<li value={option.value} {...props}>
<Checkbox
style={{ marginRight: 8 }}
checked={selected}
id={`${option.value}`}
/>
{option.label || `${option.value}`}
</li>
)}
renderInput={(params) => (
<TextField
value={value}
{...params}
placeholder={global.translate(placeholder)}
/>
)}
/>
this one is my multi-select autocomplete:
<Autocomplete
onChange={(e: any, value) => {
onChange(value);
}}
value={value}
sx={{ ...sx }}
multiple
id={id}
options={options}
disableCloseOnSelect
defaultValue={[...defaultValues]}
getOptionLabel={(option) => option.label}
isOptionEqualToValue={(newValue, option) =>
newValue.value === option.value
}
renderOption={(props, option, { selected }) => (
<li value={option.value} {...props}>
<Checkbox
icon={<CheckBoxOutlineBlankIcon fontSize="small" />}
checkedIcon={<CheckBoxIcon fontSize="small" />}
style={{ marginRight: 8 }}
checked={selected}
id={option.value}
/>
{option.label}
</li>
)}
renderInput={(params) => (
<TextField {...params} placeholder={placeholder} />
)}
/>
In your single-select mode Autocomplete component, you send handleChangeValue if only newValue exists.
So, in your single-select mode, you need to change this code:
<Autocomplete<Option<T>>
onChange={(e: any, newValue) => {
if (newValue) {
handleChangeValue(newValue.value);
}
}}
to this code:
<Autocomplete<Option<T>>
onChange={(e: any, newValue) => {
const valueToBeSent = newValue ? newValue.value : undefined;
handleChangeValue(valueToBeSent);
}}
in order to send onChange event on every value change.
MATERUAL UI Autocomplete component works fine, but I want to get object.id as onSelect event value (event.target.value), not the object.name. In other words, I want to display object.name as select item labels, but I want to get object.id as onSelect event value (event.target.value). Right now, my event.target.value is the same as select item label (object.name). Here is an example (from the Material UI documentation):
The options object is like this:
const options = [
{ id: "01", name: "Peter" },
{ id: "02", name: "Mary },
{ id: "03", name: "John" }
]
And the Autocomplete is the same like in Material UI documentation:
<Autocomplete
id="asynchronous-demo"
fullWidth
open={open}
onOpen={() => {
setOpen(true)
}}
onClose={() => {
setOpen(false)
}}
getOptionLabel={(option) => option.name}
options={options}
loading={loading}
renderInput={(params) => (
<TextField
{...params}
label="Asynchronous"
variant="outlined"
onChange={(event) => {
if (event.target.value !== '' || event.target.value !== null) {
onChangeHandle(event.target.value)
}
}}
onSelect={(event) => {
onSelectHandle(event)
}}
InputProps={{
...params.InputProps,
endAdornment: (
<React.Fragment>
{loading ? (
<CircularProgress color="inherit" size={20} />
) : null}
{params.InputProps.endAdornment}
</React.Fragment>
),
}}
/>
)}
/>
With onSelect I always get object.name as event.target.value, but I want to return object.id as event.target.value.
Does anybody knows how??
You are currently grabbing the value from TextField's onSelect, instead of Autocomplete's onChange.
<Autocomplete
...
onChange={(event, newValue) => {
onSelectHandle(newValue)
}}
renderInput={(params) => (
<TextField
{...params}
label="Asynchronous"
variant="outlined"
onChange={(event) => {
if (event.target.value !== '' || event.target.value !== null) {
onChangeHandle(event.target.value)
}
}}
...
/>
)}
/>
For more info, check out the controllable states section in the Autocomplete documentation.
I'm working with react-hook-forms and trying to reset all form fields after submit. The problem is that in my case Autocomplete accepts objects as a value.
I've tried to set the defaultValue to {}, but received the following message:
Material-UI: the getOptionLabel method of Autocomplete returned undefined instead of a string for
{}
Are there any variants how Autocomplete could be reset?
Here is a link to the CodeSandbox
A little late to the party but here's a solution if anyone else needs it.
Assuming your autocomplete is wrapped inside a Controller, all you have to do is explicitly check the value in Autocomplete. Refer below for more
<Controller
name="category"
control={control}
rules={{ required: true }}
render={({ field }) => (
<Autocomplete
fullWidth
options={categories}
{...field}
// =====================================================
// Define value in here
value={
typeof field.value === "string"
? categories.find((cat) => cat === field.value)
: field.value || null
}
// =====================================================
onChange={(event, value) => {
field.onChange(value);
}}
renderInput={(params) => (
<TextField
{...params}
label={t("product_category")}
error={Boolean(errors.productCategory)}
helperText={errors.productCategory && "Product Category is required!"}
/>
)}
/>
)}
/>
This should do the trick!
To reset the value of AutoComplete with reset of react hook form you should add the value prop to the AutoComplete, other ways the reset wont function, see the example:
import { useEffect, useState } from 'react'
import {
Autocomplete,
TextField,
reset,
} from '#mui/material'
...
const {
...
setValue,
control,
formState: { errors },
} = useForm()
useEffect(() => {
reset({
...
country: dataEdit?.country ? JSON.parse(dataEdit?.country) : null,
})
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [dataEdit])
...
<Controller
control={control}
name="country"
rules={{
required: 'Veuillez choisir une réponse',
}}
render={({ field: { onChange, value } }) => (
<Autocomplete
value={value || null}
options={countries}
getOptionLabel={(option) => option.name}
onChange={(event, values) => {
onChange(values)
setSelectedCountry(values)
setValue('region', null)
}}
renderInput={(params) => (
<TextField
{...params}
label="Pays"
placeholder="Pays"
helperText={errors.country?.message}
error={!!errors.country}
/>
)}
/>
)}
/>
I am trying to implement Auto complete having checkbox.
https://material-ui.com/components/autocomplete/#autocomplete
but when I am implementing same component in final-form I am not able to checked my option why ?
here is my code
https://codesandbox.io/s/relaxed-breeze-hv58o
<Autocomplete
{...rest}
multiple={multiple}
disableCloseOnSelect={true}
options={
multiple
? maxReached
? []
: options.filter(option => !value.includes(option.value))
: options
}
defaultValue={
multiple
? options.filter(option => value.includes(option.value))
: options.find(option => option.value === value)
}
onChange={
multiple
? (_e, values) => {
setMaxReached(value.length >= max - 1);
onChange(values.map(option => option.value));
}
: (_e, option) => onChange(option.value)
}
getOptionLabel={option => option.label}
noOptionsText={
maxReached
? formatMessage({ id: "components.autocomplete.max" }, { max })
: formatMessage({ id: "components.autocomplete.no" })
}
renderOption={(option, { selected }) => (
<React.Fragment>
<Checkbox
icon={icon}
checkedIcon={checkedIcon}
style={{ marginRight: 8 }}
checked={selected}
/>
{option.label}
</React.Fragment>
)}
renderInput={params => (
<TextField
{...params}
{...restInput}
label={label}
placeholder={placeholder || ""}
helperText={
hasError ? formatMessage({ id: error }, { label }) : helperText
}
error={hasError}
fullWidth
/>
)}
/>
);
};
You have some issues with your code (fixed version):
You are calling onChange that makes React-Final-Form re-render, which leads for Autocomplete component to re-render, and remove the select state. To fix this, you will have to use getOptionSelected option.
getOptionSelected={(option, value) => {
return option.value === value.value;
}}
options={
options
}
onChange={(_e, values) => {
onChange(values);
}
You are filtering options based to Autocomplete component, so selected option gets filtered out.
so from this:
options={
multiple
? maxReached
? []
: options.filter(option => !value.includes(option.value))
: options
}
To
options={
options
}