Material UI - How Do I Pass In Styles Through the Select Component To Change The Popover Menu Look? - material-ui

I am currently using the following to generate a select dropdown on my page:
<Select>
{options.map((option) => (
<MenuItem
className={classes.selectOption}
key={option}
value={option}
>
<ListItemText primary={option} />
</MenuItem>
))}
</Select>
When I click on the dropdown on the page, an element with MuiPaper-root class appears on the page. This shows me the list of options in menu item format. I would like to style the MuiPaper-root element.
Is there a way to do this by passing in an attribute to the <Select> component?

Yes, you can change the paper by MenuProps
https://material-ui.com/api/select/#props
const useStyles = makeStyles((theme) => ({
paper: {
"& ul": {
backgroundColor: "red",
},
}
}));
export default function CustomizedSelects() {
const classes = useStyles();
return (
<Select MenuProps={{ classes: { paper: classes.paper} }}>
{options.map((option) => (
<MenuItem
className={classes.selectOption}
key={option}
value={option}
>
<ListItemText primary={option} />
</MenuItem>
))}
</Select>);
}

Related

Radio Buttons with own labels/components (Material UI)

I would like to have my own component for my specific radio button. But the component doesn't render correctly.
I have a RadioGroup like this:
const SampleComp = (props : MyProps) => {
return <RadioGroup
defaultValue="AllTime"
name="Filter"
>
<FormControlLabel value="AllTime" control={<Radio />} label="All time" />
<FormControlLabel value="TestLabel" control={<Radio />} label={<TestLabel/>} />
</RadioGroup>
}
And I have a Testlabel to show a select component:
const TestLabel = () => {
return <FormControl fullWidth variant={'outlined'}>
<InputLabel id="demo-simple-select-label">Long text for label</InputLabel>
<Select
labelId="myField"
id="myField"
label="Long text for label"
onChange={handleChange}
>{[0, 1, 2, 3, 4, 5, 6].map(s => <MenuItem key={s} value={s}>{'value ' + s}</MenuItem>)}
</Select>
</FormControl>
}
In the end it looks like this:
I expected something like this:
Question: How can I render my component correctly when using in combination with a radio button? Or should this be done differently?
I messed around trying to get something to work but it doesn't look possible + the docs for FormControlLabel say it should take A control element. For instance, it can be a Radio, a Switch or a Checkbox.
It looks like you need to render a RadioGroup with an 'other' option and then either dynamically render or undisable a dropdown underneath the RadioGroup to achieve the behaviour you're after.
const SampleComp = () => {
const [selectedRadioValue, setSelectedRadioValue] = useState('AllTime')
const [selectedMenuItem, setSelectedMenuItem] = useState<string>()
return (
<>
<RadioGroup
value={selectedRadioValue}
name="Filter"
onChange={(_event, newValue) => setSelectedRadioValue(newValue)}
>
<FormControlLabel value="AllTime" control={<Radio />} label="All time" />
<FormControlLabel value="Other" control={<Radio />} label="Other" />
</RadioGroup>
<TextField
disabled={selectedRadioValue !== 'Other'}
label="Long text for label"
value={selectedMenuItem}
onChange={(event) => setSelectedMenuItem(event.target.value)}
fullWidth
select
>
{[0, 1, 2, 3, 4, 5, 6].map((s) => (
<MenuItem key={s} value={s}>
{'value ' + s}
</MenuItem>
))}
</TextField>
</>
)
}

How can I do a close button to a mui-select and a mui-datepicker?

I would like to add a close button to a mui-select and a mui-datepicker.
Tried to find but couldn't.
Does anyone know how to do that?
You can do this by controlling the state of the select manually. Properties open, onOpen, onClose can help you.
import * as React from 'react';
import {
OutlinedInput,
InputLabel,
MenuItem,
FormControl,
Select,
Checkbox,
Button
} from '#mui/material';
const names = [
'Oliver Hansen',
'Van Henry',
'April Tucker',
];
export default function MultipleSelectCheckmarks() {
const [personName, setPersonName] = React.useState([]);
const [showSelect, setShowSelect] = React.useState(false);
const handleChange = (e) => {
setPersonName(e.target.value.filter(Boolean));
};
return (
<FormControl sx={{ m: 1, width: 300 }}>
<InputLabel id="demo-multiple-checkbox-label">Tag</InputLabel>
<Select
multiple
open={showSelect}
onOpen={() => setShowSelect(true)}
onClose={() => setShowSelect(false)}
labelId="demo-multiple-checkbox-label"
id="demo-multiple-checkbox"
value={personName}
onChange={handleChange}
input={<OutlinedInput label="Tag" />}
renderValue={(selected) => selected.join(', ')}
>
{names.map((name) => (
<MenuItem key={name} value={name}>
<Checkbox checked={personName.includes(name)}/>
{name}
</MenuItem>
))}
<Button
color='success'
variant='contained'
onClick={() => {
setShowSelect(false);
}}
>
Close
</Button>
</Select>
</FormControl>
);
}
Thanks for the pointer Валерий Зайцев
In case you want to also close the FormControl when the user clicks away (without a dedicated close button for example), set the FormControl attribute 'focus' to false.
e.g.
<FormControl sx={{ m: 1, width: 300, focus={showSelect} }}>

Material ui Checkbox is not working in React-hook form

I want to make a Form with validation for that I used react-hook-form with Material UI. And for validation, yup and hook/resolver are also used. when I click the Checkbox I want to show another textField but the checkbox is not working. watch is used for that which comes from react-hook-form(useForm). what is my mistake? plz, help.
Here is my code: - codesanbox
You've to use the Controller or useController for the MUI checkbox, for instance:
<Controller
name="hasPhone"
control={control}
render={({ field }) => (
<FormControlLabel
control={
<Checkbox
defaultValue={data.hasPhone}
defaultChecked={data.hasPhone}
color="primary"
onChange={(e) => field.onChange(e.target.checked)}
checked={field.value}
/>
}
label="Do you have a phone"
/>
)}
/>
👉🏻 https://codesandbox.io/s/practical-morning-v6yp1
for those who are struggling with MUI5, NextJs 12 and RHF 7 in typescript, here is how I make it working
Please note that the RHF Controller is inside the FormControlLabel and not the opposite. Also the defaultValue matters
import { FormControlLabel } from "#mui/material";
import Checkbox, { CheckboxProps } from "#mui/material/Checkbox";
import { Control, Controller } from "react-hook-form";
type ICheckBoxFieldProps = CheckboxProps & {
name: string;
control: Control;
label: string;
};
const CheckBoxField: React.FC<ICheckBoxFieldProps> = ({
name,
control,
label,
defaultChecked,
...rest
}: ICheckBoxFieldProps): JSX.Element => {
return (
<FormControlLabel
label={label}
control={
<Controller
name={name}
control={control}
defaultValue={!!defaultChecked}
render={({ field }) => (
<Checkbox
checked={field.value}
onChange={field.onChange}
{...rest}
/>
)}
/>
}
/>
);
};
export default CheckBoxField;
and how to call it inside a form or a FormProvider
<CheckBoxField
name="istrue"
control={control}
defaultChecked={true}
label="isTrue"
color="success"
/>

Incorrect popover menu position when anchor element is externalized into another component

I'm new to both React and Material-UI. While examples work fine and perfectly make sense, they all use inline elements for both triggering button and the menu itself. I want to have some conditionals. For this, I'd rather have a separate component/function that renders this or that. However as soon as I move triggering button into a function, I get
Material-UI: the `anchorEl` prop provided to the component is invalid.
The anchor element should be part of the document layout.
Make sure the element is present in the document or that it's not display none.
I looked through similar questions here, but none of them looked relevant… or I didn't get them:(
Here is the code for modified example where I want to externalize button rendering into a function (to later add conditional and what not)
export default function SimpleMenu() {
const [anchorEl, setAnchorEl] = React.useState(null);
const handleClick = event => {
setAnchorEl(event.currentTarget);
};
const Qqq = () => {
return (
<Button
aria-controls="simple-menu"
aria-haspopup="true"
onClick={handleClick}
>
Broken Menu
</Button>
)
}
const handleClose = () => {
setAnchorEl(null);
};
return (
<div>
<p> hello</p>
<Button
aria-controls="simple-menu"
aria-haspopup="true"
onClick={handleClick}
>
Open Menu
</Button>
<Qqq />
<Menu
id="simple-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
>
<MenuItem onClick={handleClose}>Profile</MenuItem>
<MenuItem onClick={handleClose}>My account</MenuItem>
<MenuItem onClick={handleClose}>Logout</MenuItem>
</Menu>
</div>
);
}
Here is the fiddle
https://codesandbox.io/s/material-demo-7bnki?fontsize=14&hidenavigation=1&theme=dark . I did try to use SO code snippet, but I was getting some error about https://stacksnippets.net/js :(
What am I missing to make things work?
placing Qqq code inside SimpleManu is causing Qqq to remount on every SimpleMenu render.
Because Qqq remounted, the anchorEl reference is no longer valid.
To fix that, move Qqq outside SimpleMenu.
const Qqq = (props) => {
return (
<Button
aria-controls="simple-menu"
aria-haspopup="true"
onClick={props.handleClick}
>
Broken Menu
</Button>
)
}
export default function SimpleMenu() {
const [anchorEl, setAnchorEl] = React.useState(null);
const handleClick = event => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
return (
<div>
<p> hello</p>
<Button
aria-controls="simple-menu"
aria-haspopup="true"
onClick={handleClick}
>
Open Menu
</Button>
<Qqq handleClick={handleClick}/>
<Menu
id="simple-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
>
<MenuItem onClick={handleClose}>Profile</MenuItem>
<MenuItem onClick={handleClose}>My account</MenuItem>
<MenuItem onClick={handleClose}>Logout</MenuItem>
</Menu>
</div>
);
}
Code Sandbox
To see that Qqq really re mounts on every SimpleMenu render, go to the Code Sandbox and move Qqq to be inside SimpleMenu like before.
useEffect will print to console on every mount, and you can see what happens.

How can i change CSS of select component that inherited from inputBase, outlined and their pseudo-class

I am trying to customize CSS of a select component of material-ui this is inherited from class="MuiInputBase-root-97 MuiInput-root-84 MuiInput-underline-88 MuiInputBase-formControl-98 MuiInput-formControl-85" now i am stuck not able to change default design. Please help me, I don't have much experience with material-ui
I have tried to pass an object in classes props of select to change style applied by MuiInputBase-root-97, MuiInput-root-84, MuiInput-underline-88, MuiInputBase-formControl-98, MuiInput-formControl-85, and their pseudo class
const styles = theme => ({
root: {
'&$hover': {
color: 'red',
},
},
inputUnderline: {
minWidth: 220,
},
selectEmpty: {
marginTop: theme.spacing.unit * 2,
},
formControl: {
margin: theme.spacing.unit,
minWidth: 120,
},
});
<FormControl className={classes.formControl}>
<Select
value={this.state.age}
onChange={this.handelchange}
name="age"
displayEmpty
className={classes.selectEmpty}
classes={{
underline: classes.inputUnderline //change css of MuiInput-underline-88 and their pseudo class
root: classes.inputBaseRoot //want to change css of MuiInputBase-root-97 and their pseudo class
}}
>
<MenuItem value="" disabled>
Placeholder
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
<FormHelperText>Placeholder</FormHelperText>
</FormControl>
I want to remove border at the bottom on hover, focus, after, and before
I want a custom design in it overrides all CSS class at a select componentstrong text
In material-ui, you can override the style and customize it according to your requirement.
Please refer https://material-ui.com/customization/overrides/