I'm using Autocomplete of material-ui and I have the list of the selected values and the placeholder in the same area. I would like to set the placeholder in a new line. I'm able to change the style of placeholder using makeStyles but I didn't find a way to going in a new line.
const useStyles = makeStyles ({
placeholder: {
"& input::placeholder": {
display: "block",
},
})
renderInput={(params) => (
<TextField
/* eslint-disable react/jsx-props-no-spreading */
{...params}
classes={{root: classes.placeholder}}
label="Selected Options"
placeholder="Availables Options"
variant="outlined"
color="primary"
/>
)
You can override the renderTags method, add a wrapper component around all selected tags, and set the wrapper width to 100% to push the placeholder element down like this:
<Autocomplete
multiple
options={top100Films.map((option) => option.title)}
renderTags={(value: string[], getTagProps) => (
<div style={{ width: "100%" }}>
{value.map((option: string, index: number) => (
<Chip
variant="outlined"
label={option}
{...getTagProps({ index })}
/>
))}
</div>
)}
renderInput={(params) => <TextField {...params} />}
/>
Live Demo
Related
So this is my code:
{/* Search suggestions Autocomplete Field */}
{suggestionsFetched && <Autocomplete
disablePortal
id="combo-box-demo"
options={searchSuggestions?.salons.map((salon) => ({
type:'salon',
id:salon.id,
label:salon.name.toLowerCase()
}))
.concat(searchSuggestions?.services.map((service) => ({
type:'service',
id:service.id,
label:service.name.value.toLowerCase()
})))}
renderOption={(props, option) => {
return (
<li
{...props}
key={option.id}
>
<span style={{
fontWeight:'bolder',
textTransform:'capitalize'
}}>{option.type}:</span>
{"\u00A0"}
<span style={{
textTransform:'capitalize'
}}>{option.label}</span>
</li>
);
}}
popupIcon={<Search color='secondary' />}
sx={{
width: '100%',
[`& .${autocompleteClasses.popupIndicator}`]: {
transform: "none"
}
}}
renderInput={(params) => <TextField placeholder="Search" {...params} />}
/>}
The data I am displaying are of 2 types: salon and service. I want the default behaviour of selecting the option and displaying it. But I also want to set a state value to the type. The purpose of this is to direct to specific route based on the type.
Now since I know that the onClick function is set in the props, how do I override it. This is what I did and it did not work:
{suggestionsFetched && <Autocomplete
disablePortal
id="combo-box-demo"
options={searchSuggestions?.salons.map((salon) => ({
type:'salon',
id:salon.id,
label:salon.name.toLowerCase()
}))
.concat(searchSuggestions?.services.map((service) => ({
type:'service',
id:service.id,
label:service.name.value.toLowerCase()
})))}
renderOption={(props, option) => {
return (
<li
{...props}
onClick={()=>{
setSearchRoute(option.type)
props.onClick()
}}
key={option.id}
>
<span style={{
fontWeight:'bolder',
textTransform:'capitalize'
}}>{option.type}:</span>
{"\u00A0"}
<span style={{
textTransform:'capitalize'
}}>{option.label}</span>
</li>
);
}}
popupIcon={<Search color='secondary' />}
sx={{
width: '100%',
[`& .${autocompleteClasses.popupIndicator}`]: {
transform: "none"
}
}}
renderInput={(params) => <TextField placeholder="Search" {...params} />}
/>}
In the above code, I tried to reset the onClick prop, set my state and then call the default onClick function. But it threw this error:
TypeError: Cannot read properties of undefined (reading 'currentTarget')
How to resolve this and override default onClick prop? Or is it impossible?
So I found the solution. I just needed to write an onChange function
value={selectedSuggestion}
onChange={(event, newValue) => {
setSearchRoute(newValue.type)
setSelectedSuggestion(newValue);
}}
The newValue argument is actually the object passed in the options props.
This is so obvious and I don't know why it took me so long to figure out
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.
I'm using the React MUI Autocomplete component like in the countries example from the official doc.
My goal is to display in bold the country code, as I already did in the renderOption by simply enclosing the option.code value with HTML tags.
import * as React from 'react';
import Box from '#mui/material/Box';
import TextField from '#mui/material/TextField';
import Autocomplete from '#mui/material/Autocomplete';
export default function CountrySelect() {
return (
<Autocomplete
id="country-select-demo"
sx={{ width: 300 }}
options={countries}
autoHighlight
getOptionLabel={(option) => `${option.code} ${option.label}`} // DISPLAY THE CODE
renderOption={(props, option) => (
<Box component="li" sx={{ '& > img': { mr: 2, flexShrink: 0 } }} {...props}>
<img
loading="lazy"
width="20"
src={`https://flagcdn.com/w20/${option.code.toLowerCase()}.png`}
srcSet={`https://flagcdn.com/w40/${option.code.toLowerCase()}.png 2x`}
alt=""
/>
{option.label} (<b>{option.code}</b>) +{option.phone}
</Box>
)}
renderInput={(params) => (
<TextField
{...params}
label="Choose a country"
inputProps={{
...params.inputProps,
autoComplete: 'new-password', // disable autocomplete and autofill
}}
/>
)}
/>
);
}
I cannot find a way to reference the option.code inside the renderInput property, so I cannot figure out how to display the country code in bold also in the renderInput, since the bold is only visible when choosing an option, but not when that option is selected.
Is there a solution for this?
The main problem with this is that MUI Textfields consist of HTML <input/> tags.
Its value can only be of type string which prohibits any direct value styling but you can make use of an startAdornment like so:
...
renderInput={(params) => (
<TextField
{...params}
label="Choose a country"
inputProps={{
...params.inputProps,
autoComplete: "new-password" // disable autocomplete and autofill
}}
InputProps={{
...params.InputProps,
startAdornment: <strong>{params.inputProps.value.split(" ")[0]}</strong>
}}
/>
)}
...
Your next challenge would be to remove the additional country code from the input-value or even better, move to a controlled value approach.
I have an Autocomplete component for adding country calling code, but, the relevant country is added too with it. Like when clicked on Autocomplete drop-down list, all the countries and its specific codes are displayed. My intention is to add only the country code. See the code below for reference
const [countryData, setCountryData] = useState({});
const [newValue, setNewValue] = useState("");
useEffect(() => {
setCountryData(codes);
}, []);
<Autocomplete
id="size-small-standard"
size="small"
options={cities}
onChange={(event, value) => setNewValue(value)}
autoSelect={true}
getOptionLabel={(option) =>
option.country + " " + ` +` + option.calling_code {/* <-- How to display only calling code, but, should show both country name and calling code in drop down */}
}
defaultValue={cities[98]}
style={{ width: "100%" }}
renderInput={(params) => (
<TextField
{...params}
variant="standard"
placeholder="Search your country"
style={{ width: "40%" }}
/>
)}
/>
What would be best possible solution?
Following is the CodeSandbox link: https://codesandbox.io/s/material-demo-forked-3ljj2
You can change your getOptionLabel to show only the phone prefix and then use renderOption to show the name with the country's phone prefix
return (
<div className={classes.root}>
<Autocomplete
id="size-small-standard"
size="small"
options={cities}
onChange={(event, value) => setNewValue(value)}
autoSelect={true}
getOptionLabel={(option) => `+ ${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>
);
Live Demo
UPDATE:
Here is a better example, where you can still search for the country.
Live Demo
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.