MUI Autocomplete endAdornment blowing away default clearIcon - reactjs

I am using an MUI Autocomplete and have added an endAdornment loader to the Textfield while the options are being fetched (from an external source), however this is overriding MUI's clearIcon (presumably because it is also an endAdornment). How do ensure that the default clearIcon remains? Here is my code -
<Autocomplete
style={{ margin: 'auto' }}
options={itemOptions}
getOptionLabel={(option: Item) => option? option.name:''}
value={selectedItem}
inputValue={filterInput}
onInputChange={(e, v) => handleInputChange(v)}
onChange={(e, val) => {
if (val) {
handleItemSelect(val)
}
}}
renderInput={(params) => (
<TextField
{...params}
label="Items"
variant="outlined"
style={{ width: '300px' }}
InputProps={{
...params.InputProps,
endAdornment: (
<>
{loading ? <CircularProgress color="inherit" size={25} /> : null}
</>
),
}}
type="text"
/>
)}
/>

I figured it out, just need to add:
{params.InputProps.endAdornment}
to my endAdornment like so:
endAdornment: (
<>
{loading ? <CircularProgress color="inherit" size={25} /> : null}
{params.InputProps.endAdornment}
</>
),

Related

MUI textfield label not floating to the top left properly

I try to use the MUI in my project, and all the input fields I use don't behave correctly.
it supposed to look like this
but when I use it it will look like this
import Box from '#mui/material/Box'
import TextField from '#mui/material/TextField'
import Autocomplete from '#mui/material/Autocomplete'
<Autocomplete
className="mt-3"
size="small"
id="country-select-demo"
options={arr}
autoHighlight
getOptionLabel={(option) => option.label}
renderOption={(props, option) => (
<Box
component="li"
sx={{ '& > img': { mr: 2, flexShrink: 0 } }}
{...props}
>
{option.label}
</Box>
)}
renderInput={(params) => (
<TextField
{...params}
label="Choose.."
inputProps={{
...params.inputProps,
}}
/>
)}
I just found out that uninstalling the react-bootstrap fix this problem.

How can I render input into Chip in material ui without multiple set?

<StyledAutocomplete
sx={{ width: "40%", ml: "10px", mr: "10px" }}
id='multiple-limit-tags'
options={locationOptions}
filterSelectedOptions
autoComplete={true}
onChange={handleLocationChange}
getOptionLabel={option => option.label}
freeSolo
autoHighlight
forcePopupIcon
autoFocus
renderTags={(value, getTagProps) =>
value.map((option, index) => (
<Chip key={index} variant='filled' label={option} {...getTagProps({ index })} />
))
}
renderInput={params => (
<TextField
{...params}
variant='outlined'
label='Location'
placeholder={selectedLocations.length < 1 ? "Country" : ""}
/>
)}
/>
I wanna be able to render the input into a chip without multiple prop, the renderTags props only seems to work on multiple

Material ui Autocomplete endInputAdornment custom elements not centered

When setting material ui <Autocomplete /> with variant='filled' The endInputAdornments does not center to the AutoComplete.
Codesandbox with both variants for reference here
<Autocomplete
disablePortal
id="combo-box-demo"
options={top100Films}
sx={{ width: 300, mt: 2 }}
renderInput={(params) => (
<TextField
{...params}
label="Movie"
variant="filled" //With filled it does not center anymore
InputProps={{
...params.InputProps,
endAdornment: (
<React.Fragment>
{params.InputProps.endAdornment}
<IconButton
color="primary"
aria-label="upload picture"
component="span"
>
<PhotoCamera />
</IconButton>
</React.Fragment>
)
}}
/>
I found a github issue where they fixed it for the inputProps internally but I cant seem to find a way to do the same with my own adornment elements.
The only prop that seems relevant is popupIcon but i still want that default feature. I just want to be able to add more IconButtons to the endInputAdornments
You can style the container for the icon by using a <div> instead of <React.Fragment>:
endAdornment: (
<div style={{ marginTop: "-19px" }}>
{params.InputProps.endAdornment}
<IconButton
color="primary"
aria-label="upload picture"
component="div"
>
<PhotoCamera />
</IconButton>
</div>
)
Here's the sandbox link
Why -19px? Because with variant="filled" the container for the text and icon is shifted down by 19px:
The popup icon of Autocomplete is vertically centered because of this styles. You can add your own styles to center the icon next to it by modifying the styles from the source a bit:
<Autocomplete
options={top100Films}
renderInput={(params) => (
<TextField
{...params}
label="Movie"
variant="filled"
InputProps={{
...params.InputProps,
sx: {
// this is necessary if you don't want to input value to be
// placed under the icon at the end
'&&&': { pr: '70px' },
},
endAdornment: (
<React.Fragment>
{params.InputProps.endAdornment}
<IconButton
color="primary"
sx={{
position: 'absolute',
p: 0,
right: 40,
top: 'calc(50% - 12px)', // Center vertically
}}
>
<PhotoCamera />
</IconButton>
</React.Fragment>
),
}}
/>
)}
/>

How to set default value in Autocomplete Material UI?

In a React project, I have an Autocomplete component which has country name and its relevant calling codes displayed in drop-down list. When selected on list renders the desired data, but, when refreshed, data is null and doesn't show the default data.
const [newValue, setNewValue] = useState({});
const [textToggle, textToggleState] = useState(false);
render(
<div
style={{ cursor: "pointer" }}
onClick={() => {
textToggleState(!textToggle);
}}
>
<h5>+{newValue == null ? "91" : newValue.calling_code}</h5> {/* <-- Value gets null when refreshed */}
</div>
{textToggle ? (
<Autocomplete
id="size-small-standard"
size="small"
options={cities}
onChange={(event, value) => {
setNewValue(value);
textToggleState(!textToggle);
}}
autoSelect={true}
getOptionLabel={(option) =>
`${option.country}` + `+ ${option.calling_code}`
}
renderOption={(option) => (
<>{`${option.country} + ${option.calling_code}`}</>
)}
//defaultValue={cities[98]}
style={{ width: "100%" }}
renderInput={(params) => (
<TextField
{...params}
variant="standard"
placeholder="Search your country"
style={{ width: "40%" }}
/>
)}
/>
) : (
""
)}
)
Following is the CodeSandbox link: https://codesandbox.io/s/how-to-add-only-single-value-from-autocomplete-in-material-ui-forked-tu218
You can pass a value prop to autocomplete component with the newValue. But newValue is an empty object by default that doesn't exist in the options array you are passing to the autocomplete so it will show undefined + undefined in the default case. You can make that null and add null check there in the autocomplete itself or you can assign a value directly in your useState So as you are having a check for null and using 91 code so instead you can assign that value to the newValue itself directly. Check the code below I have added the value field here
<Autocomplete
id="size-small-standard"
size="small"
options={cities}
value={newValue !== null ? newValue : cities[98]}
onChange={(event, value) => {
setNewValue(value);
textToggleState(!textToggle);
}}
autoSelect={true}
getOptionLabel={(option) =>
`${option.country}` + `+ ${option.calling_code}`
}
renderOption={(option) => (
<>{`${option.country} + ${option.calling_code}`}</>
)}
//defaultValue={cities[98]}
style={{ width: "100%" }}
renderInput={(params) => (
<TextField
{...params}
variant="standard"
placeholder="Search your country"
style={{ width: "40%" }}
/>
)}
/>
Or you can just pass newValue to the value field and assign the default value in the newValue useState as shown below
const [newValue, setNewValue] = useState(cities[98]);
.
.
.
.
<Autocomplete
id="size-small-standard"
size="small"
options={cities}
value={newValue}
onChange={(event, value) => {
setNewValue(value);
textToggleState(!textToggle);
}}
autoSelect={true}
getOptionLabel={(option) =>
`${option.country}` + `+ ${option.calling_code}`
}
renderOption={(option) => (
<>{`${option.country} + ${option.calling_code}`}</>
)}
//defaultValue={cities[98]}
style={{ width: "100%" }}
renderInput={(params) => (
<TextField
{...params}
variant="standard"
placeholder="Search your country"
style={{ width: "40%" }}
/>
)}
/>

How to open the dropdown list in Autocomplete Material-UI by default?

In an Autocomplete Form, the data for country and its relevant codes are displayed. When the input text is focused the drop-down list is populated. My intention is to pre load array of data without focus requirement. See the code for example
const [newValue, setNewValue] = useState(null);
const [textToggle, textToggleState] = useState(false);
render(
<div
style={{ cursor: "pointer" }}
onClick={() => {
textToggleState(!textToggle);
}}
>
<h5>+{newValue == null ? "91" : newValue.calling_code}</h5>
</div>
{textToggle ? (
<Autocomplete
id="size-small-standard"
size="small"
options={cities}
onChange={(event, value) => {
setNewValue(value);
textToggleState(!textToggle);
}}
autoSelect={true}
getOptionLabel={(option) =>
`${option.country}` + `+ ${option.calling_code}`
}
renderOption={(option) => (
<>{`${option.country} + ${option.calling_code}`}</>
)}
//defaultValue={cities[98]}
style={{ width: "100%" }}
renderInput={(params) => (
<TextField
{...params}
variant="standard"
placeholder="Search your country"
style={{ width: "40%" }}
/>
)}
/>
) : (
""
)}
</div>
)
Here you can see data is displayed on input text focus. What could be the best possible solution to
pre-load data?
CodeSandbox Link: https://codesandbox.io/s/how-to-add-only-single-value-from-autocomplete-in-material-ui-forked-tu218
Just take control of the open state of the Autocomplete and set the default value to true:
export default function ComboBox() {
// default value to true to open at first render
const [open, setOpen] = useState(true);
return (
<Autocomplete
open={open}
onOpen={() => setOpen(true)}
onClose={() => setOpen(false)}
options={top100Films}
getOptionLabel={(option) => option.title}
renderInput={(params) => (
<TextField {...params} label="Combo box" variant="outlined" />
)}
/>
);
}
Live Demo
I think what you need is to use AutoComplete as Combobox.
<Autocomplete
id="combo-box-demo"
options={top100Films}
getOptionLabel={(option) => option.title}
style={{ width: 300 }}
renderInput={(params) => <TextField {...params} label="Combo box" variant="outlined" />}
/>
This will pre-populate it.
Visit this: https://material-ui.com/components/autocomplete/#combo-box
Hope it helps. if not, please elaborate your question if you want something else.

Resources