Add a text field in MUI Autocomplete options dropdown - javascript

I want to add an editable text field in dropdown options of MUI Autocomplete.
I was able to add MUI text field by adding it in renderOption prop of Autocomplete.
Problem
I am not able to edit the text fields since the autocomplete selection overrides it.
<Autocomplete
open={open}
multiple
value={!!value ? [value] : []}
classes={{ popupIndicatorOpen: classes.popupOpen }}
closeIcon={null}
popupIcon={<KeyboardArrowDownIcon style={{ opacity: 0.6 }}/>}
forcePopupIcon
style={{ width: 300 }}
options={options} //array
getOptionLabel={opt => isInstanceOfIRange(opt) ? Concatenate([opt.min.value, opt.max.value], ' - ') : opt.value.toString() || ''}
renderTags={(opts, getTagProps) =>
opts.map((opt, index) => (
<CustomTag key={index.toString()} opt={opt} {...getTagProps({ index })} classes={classes} />)
)}
onChange={handleChange}/
renderInput={params => (
<TextField
{...params}
label={props.label}
variant='filled'
onFocus={() => setOpen(true)}
onInput={onInputChange}
/>
)}
renderOption={(option, { selected }) => (
<CustomOption option={option} selected={selected} />
)}
PopperComponent={PopperComponent}
PaperComponent={PaperComponent}
/>
Custom Options rendering text box
const CustomOption = ({ selected, option }) => (
<div style={{ display: 'flex', flexDirection: 'row' }}>
<Checkbox
size="small"
color="primary"
checked={selected}
style={{ marginRight: 8 }}
icon={<RadioButtonUncheckedIcon />}
checkedIcon={<RadioButtonCheckedIcon />}
/>
{
isInstanceOfIRange(option) ? <RangeRender option={option} /> : <SingleRender
option={option} />
}
</div>
);
The Two text boxes are rendered using this component
const RangeRender = ({ option: { min, max } }) => {
const { labelPostfix, labelPrefix } = useContext(DropDownContext);
const inputProps = labelPrefix ? {
startAdornment: <InputAdornment position="start">{labelPrefix}</InputAdornment>,
} : labelPostfix ? { endAdornment: <InputAdornment position="end">{labelPostfix}
</InputAdornment>,} : {};
return (
<Box style={{ display: 'flex', gap: 12 }}>
<NummberField
type="number"
variant="outlined"
value={min.value}
InputProps={inputProps}
/>
<NummberField
type="number"
variant="outlined"
value={max.value}
InputProps={inputProps}
/>
</Box>);
};

Related

Applying InputAdornment to MUI AutoComplete removes the options list

I built an AutoComplete component that looks like this:
<Autocomplete
freeSolo
size="small"
id="filter-locks-autocomplete"
options={json_list ? json_list : []}
groupBy={(option) => option.lock.building}
getOptionLabel={(option) => (option.name)}
inputValue={inputValue}
onInputChange={(event, newInputValue) => setInputValue(newInputValue)}
renderInput={(params) => (
<TextField
{...params}
variant="standard"
label={'lock'}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<Search sx={{ color: "black", fontSize: 20, marginLeft: "2px" }} />
{params.InputProps.startAdornment}
</InputAdornment>
),
}}
/>
)}
/>;
However, the list of options do no longer appear when clicking inside the box.
If I remove the InputProps from <TextField /> like so:
<Autocomplete
freeSolo
size="small"
id="filter-locks-autocomplete"
options={json_list ? json_list : []}
groupBy={(option) => option.lock.building}
getOptionLabel={(option) => option.name}
inputValue={inputValue}
onInputChange={(event, newInputValue) => setInputValue(newInputValue)}
ListboxProps={{ sx: { zIndex: 1500 } }}
renderInput={(params) => (
<TextField {...params} variant="standard" label={"lock name"} />
)}
/>;
the list of options show as expected.
Is there a way I can add an inputAdornment (just a search icon) to AutoComplete component without removing the Options list?
Here I found the solution, you can try following code
<Autocomplete
id="tags-standard"
options={top100Films}
getOptionLabel={option => option.title}
defaultValue={[top100Films[13]]}
renderInput={params => {
return (
<TextField
{...params}
variant="standard"
label="Multiple values"
placeholder="Favorites"
fullWidth
InputProps={{
...params.InputProps,
startAdornment: (
<>
<InputAdornment position="start">
<SearchIcon />
</InputAdornment>
{params.InputProps.startAdornment}
</>
)
}}
/>
);
}}
/>
It is working fine. you can also check here in CodeSandbox
for more details check this Github material-ui issue

MUI multiselect chip select same data from two array base on id's?

<Select
value={value ? value : personName}
labelId="demo-multiple-chip-label"
id="demo-multiple-chip"
multiple
name="mis"
onChange={handleChange}
input={<OutlinedInput id="select-multiple-chip" label="Chip" />}
renderValue={(selected) => (
<Box sx={{ display: "flex", flexWrap: "wrap", gap: 0.5 }}>
{selected.map((value) => (
<Chip key={value} label={value} />
))}
</Box>
)}
MenuProps={MenuProps}
>
{names.map((name) => (
<MenuItem
key={name}
value={name}
style={getStyles(name, personName, theme)}
>
{name}
</MenuItem>
))}
</Select>
I have two arrays, what I want, I want to select all the objects that are same by id's.
Thanks for helping in advance....

React Hooks : Change state of multiple items

I have a list of icons.
When I click on one of them, I want it to :
1/ change state to day or night
2/ change icon image to a sun or a moon.
But with the code that I've written, if I click on one, it changes all the icons image and only one state is linked to all.
How can I do so each icons has it own state and when i click on icon, only the icon clicked changes to a moon or a sun and not all of them ?
My code :
export default function MyModal() {
const [isVisible, setVisible] = useState(false);
const [isDay, setDay] = useState(true);
const { RangePicker } = DatePicker;
const { Option } = Select;
const style = {
verticalAlign: "middle",
marginRight: 10,
};
function handleDayNight() {
isDay === true ? setDay(false) : setDay(true);
console.log("isDay =", isDay);
}
function handleSelectChange(value) {
console.log(`selected ${value}`);
}
function handleCheckChange(checkedValues) {
console.log("checked =", checkedValues);
}
return (
<div>
<Button type="primary" onClick={() => setVisible(true)}>
Add an exception
</Button>
<Modal
title="Add an exception"
style={{ top: 20 }}
visible={isVisible}
onOk={() => setVisible(false)}
onCancel={() => setVisible(false)}
>
<p>Exceptions name</p>
<Input placeholder="80% Wednesday" />
<p style={{ marginTop: 10 }}>Select date</p>
<RangePicker onChange={([date]) => console.log(date)} />
<p style={{ marginTop: 10 }}>Frequency</p>
<Select
defaultValue="Weekly"
style={{ width: 120 }}
onChange={handleSelectChange}
>
<Option value="daily">Daily</Option>
<Option value="weekly">Weekly</Option>
<Option value="monthly">Monthly</Option>
</Select>
<Divider />
<Checkbox.Group style={{ width: "100%" }} onChange={handleCheckChange}>
<div>
{isDay === true ? (
<Sun style={style} onClick={handleDayNight} />
) : (
<Moon style={style} onClick={handleDayNight} />
)}
<Checkbox value="Monday">Monday</Checkbox>
<br></br>
{isDay === true ? (
<Sun style={style} onClick={handleDayNight} />
) : (
<Moon style={style} onClick={handleDayNight} />
)}
<Checkbox value="Tuesday">Tuesday</Checkbox>
<br></br>
{isDay === true ? (
<Sun style={style} onClick={handleDayNight} />
) : (
<Moon style={style} onClick={handleDayNight} />
)}
<Checkbox value="Wednesday">Wednesday</Checkbox>
<br></br>
{isDay === true ? (
<Sun style={style} onClick={handleDayNight} />
) : (
<Moon style={style} onClick={handleDayNight} />
)}
<Checkbox value="Thursday">Thursday</Checkbox>
<br></br>
<Checkbox value="Friday">Friday</Checkbox>
<br></br>
<Checkbox value="Saturday">Saturday</Checkbox>
<br></br>
<Checkbox value="Sunday">Dimanche</Checkbox>
</div>
</Checkbox.Group>
</Modal>
</div>
);
}
Use a separate component for each of those, so you can have individual separate states inside those components. Eg, replace all of
{isDay === true ? (
<Sun style={style} onClick={handleDayNight} />
) : (
<Moon style={style} onClick={handleDayNight} />
)}
with
<SunMoon style={style} />
const SunMoon = ({ style }) => {
const [isDay, setDay] = useState(true);
const handleDayNight = () => setDay(!isDay);
return isDay
? <Sun style={style} onClick={handleDayNight} />
: <Moon style={style} onClick={handleDayNight} />;
};

Material UI <Autocomplete/> remove browser suggestion

I have problem with Material-ui Autocomplete:
import Autocomplete from "#material-ui/lab/Autocomplete";
I am using then in:
<Autocomplete
id="checkboxes-tags-demo"
autoComplete={false}
options={states}
disableCloseOnSelect
getOptionLabel={(option) => option.name}
onChange={onStateChange}
renderOption={(option, { selected }) => (
<React.Fragment>
<Checkbox
icon={icon}
checkedIcon={checkedIcon}
style={{ marginRight: 8 }}
checked={selected}
/>
{option.name}
</React.Fragment>
)}
style={{ width: "100%" }}
renderInput={(params) => (
<TextField
{...params}
variant="outlined"
label="State"
placeholder="Enter state"
/>
)}
/>
Nothing important in this code but I face this issue:
I am getting the browser suggestion. How I can remove it ?
As mentioned in this SO question, you should add autoComplete="off" to your TextField.

Filtering When a Button is clicked

I currently have a search input which filters through the github repos. I then have a drop down select which allows a user to filter based on the language of the code used. I instead would like to use buttons rather than a drop down. Is there a way to filter the results on click as opposed to onChange like I am doing with the drop down. My code is as follows:
const Profile = () => {
const [formData, setFormData] = useState(INITIAL_STATE)
const [updated, setUpdated] = useState(false)
const [created, setCreated] = useState(false)
const { data } = useContext(GithubContext)
const handleUpdated = () => {
setUpdated(!updated)
data &&
data.sort((a, b) => {
if (updated) return a.updated_at > b.updated_at ? -1 : 1
return a.updated_at > b.updated_at ? 1 : -1
})
}
const handleCreated = () => {
setCreated(!created)
data &&
data.sort((a, b) => {
if (created) return a.created_at > b.created_at ? -1 : 1
return a.created_at > b.created_at ? 1 : -1
})
}
const handleInputChange = field => e => {
setFormData({ ...formData, [field]: e.target.value })
}
const classes = useStyles()
return (
<>
<div style={{ marginTop: 85, marginBottom: 85 }}>
<Container className={classes.dashboardContainer}>
<Card className={classes.card} style={{ width: '100%' }}>
<CardContent className={classes.content}>
<div className={classes.form}>
<Grid
container
spacing={2}
alignItems='center'
justify='space-between'
>
<Grid item sm={4} xs={12} className={classes.grid}>
<SelectStatus
language={formData.language}
handleInputChange={handleInputChange}
/>
</Grid>
<Grid item sm={4} xs={12} className={classes.grid}>
<TextField
className={classes.jobField}
margin='normal'
fullWidth
id='search'
name='search'
label='Search by Title'
placeholder='Search by Title'
onChange={handleInputChange('search')}
value={formData.search}
/>
</Grid>
<Grid item sm={2} xs={12} className={classes.grid}>
<Button
variant='contained'
color='primary'
onClick={handleUpdated}
>
Updated {updated ? '(oldest)' : '(newest)'}
</Button>
</Grid>
<Grid item sm={2} xs={12} className={classes.grid}>
<Button
fullWidth
variant='contained'
color='primary'
onClick={handleCreated}
>
Created {created ? '(oldest)' : '(newest)'}
</Button>
</Grid>
</Grid>
</div>
</CardContent>
</Card>
<div
style={{
textAlign: 'center'
}}
>
<Button variant='outlined' color='primary'>
JavaScript
</Button>
<Button variant='outlined' color='primary'>
Primary
</Button>
<Button variant='outlined' color='primary'>
Secondary
</Button>
<Button variant='outlined' color='primary'>
Disabled
</Button>
<Button variant='outlined' color='primary'>
Link
</Button>
<br />
</div>
</Container>
{!data ? (
<h1 className={classes.loading}>Initializing Repos...</h1>
) : (
<Container style={{ padding: 10 }}>
{!data ? (
<div style={{ placeItems: 'center' }}>Loading...</div>
) : (
<Grid container alignItems='center' spacing={4}>
{data &&
data
.filter(data => {
if (formData.language === 'All') return true
return data.language === formData.language
})
.filter(data => {
if (formData.search === '') return true
return (data.name + data.language)
.toLowerCase()
.includes(formData.search.toLowerCase())
})
.map(user => <RepoCard key={user.id} user={user} />)}
</Grid>
)}
</Container>
)}
</div>
</>
)
}
export default Profile
and here is the drop down component:
import React, { useRef } from "react"
// MUI stuff
import Select from "#material-ui/core/Select"
import InputLabel from "#material-ui/core/InputLabel"
import MenuItem from "#material-ui/core/MenuItem"
import FormControl from "#material-ui/core/FormControl"
const SelectStatus = ({ language, handleInputChange }) => {
const inputLabel = useRef(null)
return (
<FormControl style={{ width: "100%" }}>
<InputLabel ref={inputLabel} id='demo-simple-select-outlined-label'>
Status
</InputLabel>
<Select
labelId='demo-simple-select-outlined-label'
id='demo-simple-select-outlined'
value={language}
onChange={handleInputChange("language")}
fullWidth
>
<MenuItem value='All'>All</MenuItem>
<MenuItem value='HTML'>HTML</MenuItem>
<MenuItem value='JavaScript'>JavaScript</MenuItem>
<MenuItem value='Ruby'>Ruby</MenuItem>
</Select>
</FormControl>
)
}
export default SelectStatus
Any suggestions would be extremely helpful!!!
You can just use buttons and add them a value so it will work exactly the same as the dropdown
const handleInputChange = field => e => {
setFormData({ ...formData, [field]: e.target.value })
}
<Button onClick={handleInputChange('language')} value="All">All</Button>
<Button onClick={handleInputChange('language')} value="HTML")>HTML</Button>
<Button onClick={handleInputChange('Javascript')} value="Javascript">JavaScript</Button>
<Button onClick={handleInputChange('Ruby')} value="Ruby">Ruby</Button>

Categories