I would like to make select dropdown using by InputBase component. The select box shows correctly, but dropdown options doesn't show when I click the field. I had tried other inputComponent like input, it's work fine.
I want the label above on the field and I know that I can use native select to make this. However, I want to share same styles between these components.
Does anyone know how to use input base to make select component?
The code provided below:
import React from "react";
import "./styles.css";
import {
FormControl,
InputLabel,
InputBase,
MenuItem
} from "#material-ui/core";
import { withStyles, fade } from "#material-ui/core/styles";
export default function App() {
const BootstrapInput = withStyles((theme) => ({
root: {
"label + &": {
marginTop: "20px"
}
},
input: {
position: "relative",
backgroundColor: theme.palette.common.white,
border: "1px solid #ccc",
fontSize: 14,
width: "380px",
height: "12px",
padding: "10px 12px",
transition: theme.transitions.create(["border-color", "box-shadow"]),
"&:focus": {
boxShadow: `${fade(theme.palette.primary.main, 0.25)} 0 0 0 0.2rem`,
borderColor: theme.palette.primary.main
}
}
}))(InputBase);
return (
<div className="App">
<FormControl>
<InputLabel shrink htmlFor="personalTitle">
Age
</InputLabel>
<BootstrapInput inputComponent="select" name="personalTitle">
<MenuItem>20</MenuItem>
<MenuItem>30</MenuItem>
<MenuItem>40</MenuItem>
</BootstrapInput>
</FormControl>
</div>
);
}
CodeSandbox link:
https://codesandbox.io/s/select-on-inputbase-0ufes?file=/src/App.js:0-1209
You Can use material-ui select component to manage select box easily. You can check more details using below link
https://material-ui.com/components/selects/
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import InputLabel from '#material-ui/core/InputLabel';
import MenuItem from '#material-ui/core/MenuItem';
import FormHelperText from '#material-ui/core/FormHelperText';
import FormControl from '#material-ui/core/FormControl';
import Select from '#material-ui/core/Select';
const useStyles = makeStyles((theme) => ({
formControl: {
margin: theme.spacing(1),
minWidth: 120,
},
selectEmpty: {
marginTop: theme.spacing(2),
},
}));
export default function SimpleSelect() {
const classes = useStyles();
const [age, setAge] = React.useState('');
const handleChange = (event) => {
setAge(event.target.value);
};
return (
<div>
<FormControl className={classes.formControl}>
<InputLabel id="demo-simple-select-label">Age</InputLabel>
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
value={age}
onChange={handleChange}
>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
</div>
)
}
Related
I have created a simple select component with menu items (material ui v 4.12). But the select component is being displayed entirely wrong. There are no console errors. What might be wrong here?
Here is the screenshot and the code.
import React, { useState } from "react";
import FormControl from "#material-ui/core/FormControl";
import InputLabel from "#material-ui/core/InputLabel";
import Select from "#material-ui/core/InputLabel";
import MenuItem from "#material-ui/core/MenuItem";
import { makeStyles } from "#material-ui/core";
const mockData = ["list01", "list02"];
function TestPage() {
const useStyles = makeStyles((theme) => ({
formControl: {
margin: theme.spacing(1),
minWidth: 120,
},
selectEmpty: {
marginTop: theme.spacing(2),
},
}));
const classes = useStyles();
const [data, setData] = useState("");
return (
<div className="test">
<h2>TEST</h2>
<FormControl
variant="outlined"
classes={{
root: classes.formControl,
}}
>
<InputLabel id="demo-simple-select-outlined-label">
Select list
</InputLabel>
<Select
id="test-select-outlined"
value={data}
onChange={(e) => setData(e.target.value)}
label="Select list"
>
{mockData.map((item, index) => (
<MenuItem key={index + 1} value={item}>
{item}
</MenuItem>
))}
</Select>
</FormControl>
</div>
);
}
export default TestPage;
Your Select import is wrong:
import Select from "#material-ui/core/InputLabel";
just change it to:
import Select from "#material-ui/core/Select";
This is my code,
import { AppBar, createStyles, MenuItem, Select, Toolbar, Typography } from '#mui/material';
import { makeStyles } from '#mui/styles';
import { useState } from 'react';
const useStyles = makeStyles((theme) =>
createStyles({
selectRoot: {
color: "white",
}
}),
);
const Navbar = () => {
const classes = useStyles();
const [sort, setSort] = useState(1);
return (
<AppBar position="static">
<Toolbar>
<Typography variant="h6" sx={{ flexGrow: 1}}>Tools</Typography>
<Select
variant="standard"
value={sort}
className={classes.selectRoot}
onChange={(event) => setSort(event.target.value)}
>
<MenuItem value={1}>Default sort</MenuItem>
<MenuItem value={2}>Sort by Title ASC</MenuItem>
<MenuItem value={3}>Sort by Title DESC</MenuItem>
</Select>
</Toolbar>
</AppBar>
)
}
export default Navbar;
What I need to change the color of select tag. In inspect seems like overridden by this class.
.css-a88p61-MuiInputBase-root-MuiInput-root{
color: rgba(0, 0, 0, 0.87);
}
You need to use .MuiMenuItem-root inside your select tag , this will color your entire menuItems.
MenuProps={{
sx: {
"&& .MuiMenuItem-root":{
backgroundColor: "red",
color: "orange"
}
}
}}
But if you don't want to apply color to a specific menuItem then you need to use the .MuiMenuItem-gutters class in Select Component and set disableGutters={true} to the menuItem to which you don't want to apply the color
Example using .MuiMenuItem-root class
import { AppBar, createStyles, MenuItem, Select, Toolbar, Typography } from '#mui/material';
import { makeStyles } from '#mui/styles';
import { useState } from 'react';
const useStyles = makeStyles((theme) =>
createStyles({
selectRoot: {
color: "white",
},
menuItem:{
color: "red",
}
}),
);
const Select = () => {
const classes = useStyles();
const [sort, setSort] = useState(1);
return (
<AppBar position="static">
<Toolbar>
<Typography variant="h6" sx={{ flexGrow: 1}}>Tools</Typography>
<Select
variant="standard"
value={sort}
className={classes.selectRoot}
onChange={(event) => setSort(event.target.value)}
MenuProps={{
sx: {
"&& .MuiMenuItem-root":{
backgroundColor: "red",
color: "orange"
}
}
}}
>
<MenuItem value={1}>Default sort</MenuItem>
<MenuItem value={2}>Sort by Title ASC</MenuItem>
<MenuItem value={3}>Sort by Title DESC</MenuItem>
</Select>
</Toolbar>
</AppBar>
)
}
export default Select;
Example using .MuiMenuItem-gutters class
import { AppBar, createStyles, MenuItem, Select, Toolbar, Typography } from '#mui/material';
import { makeStyles } from '#mui/styles';
import { useState } from 'react';
const useStyles = makeStyles((theme) =>
createStyles({
selectRoot: {
color: "white",
},
}),
);
const Select = () => {
const classes = useStyles();
const [sort, setSort] = useState(1);
return (
<AppBar position="static">
<Toolbar>
<Typography variant="h6" sx={{ flexGrow: 1}}>Tools</Typography>
<Select
variant="standard"
value={sort}
className={classes.selectRoot}
onChange={(event) => setSort(event.target.value)}
MenuProps={{
sx: {
"&& .MuiMenuItem-gutters": {
backgroundColor: "pink",
color: "red"
},
}
}}
>
<MenuItem disableGutters = {true} value={1}>Default sort</MenuItem>
<MenuItem value={2}>Sort by Title ASC</MenuItem>
<MenuItem value={3}>Sort by Title DESC</MenuItem>
</Select>
</Toolbar>
</AppBar>
)
}
export default Select;
Refer documentation for more css properties
I have
import CaretDownIcon from 'src/../public/images/svg/caret-down.svg';
<Select
className={selectClassName}
data-testid={testId}
// IconComponent={<SvgIcon>{CaretDownIcon}</SvgIcon>}
// IconComponent={CaretDownIcon}
inputProps={{
name,
id: labelId,
}}
{...rest}
>
I tried both of those commented lines, but no dice. What's the right way?
You need to create a component for your custom svg icon. Copy the path from the svg file to make a component as shown below:
function CustomSvgIcon(props) {
return (
<SvgIcon {...props}>
<path d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z" />
</SvgIcon>
);
}
then you can use that with IconComponent={CustomSvgIcon}.
Here's a full working example:
import React from "react";
import PropTypes from "prop-types";
import { withStyles } from "#material-ui/core/styles";
import InputLabel from "#material-ui/core/InputLabel";
import MenuItem from "#material-ui/core/MenuItem";
import FormControl from "#material-ui/core/FormControl";
import Select from "#material-ui/core/Select";
import SvgIcon from "#material-ui/core/SvgIcon";
const styles = (theme) => ({
root: {
display: "flex",
flexWrap: "wrap"
},
formControl: {
margin: theme.spacing.unit,
minWidth: 120
},
selectEmpty: {
marginTop: theme.spacing.unit * 2
}
});
function CustomSvgIcon(props) {
return (
<SvgIcon {...props}>
<path d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z" />
</SvgIcon>
);
}
class SimpleSelect extends React.Component {
state = {
age: "",
name: "hai"
};
handleChange = (event) => {
this.setState({ [event.target.name]: event.target.value });
};
render() {
const { classes } = this.props;
return (
<form className={classes.root} autoComplete="off">
<FormControl className={classes.formControl}>
<InputLabel htmlFor="age-simple">Age</InputLabel>
<Select
value={this.state.age}
onChange={this.handleChange}
inputProps={{
name: "age",
id: "age-simple"
}}
IconComponent={CustomSvgIcon}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
</form>
);
}
}
SimpleSelect.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(SimpleSelect);
It is also possible to create a React component from an imported SVG file, but this is dependent on your build configuration. If you are using create-react-app then this will work (see this article for details).
Below is an example using the import approach. This uses import { ReactComponent as TestSvgAsComponent } from "./test.svg"; to get a React component from the SVG file. The other step necessary is to add in the styles that would be applied by SvgIcon (classes.icon from useIconStyles in the example).
import React from "react";
import PropTypes from "prop-types";
import { withStyles, makeStyles } from "#material-ui/core/styles";
import InputLabel from "#material-ui/core/InputLabel";
import MenuItem from "#material-ui/core/MenuItem";
import FormControl from "#material-ui/core/FormControl";
import Select from "#material-ui/core/Select";
import { ReactComponent as TestSvgAsComponent } from "./test.svg";
import clsx from "clsx";
const styles = (theme) => ({
root: {
display: "flex",
flexWrap: "wrap"
},
formControl: {
margin: theme.spacing.unit,
minWidth: 120
},
selectEmpty: {
marginTop: theme.spacing.unit * 2
}
});
const useIconStyles = makeStyles({
// This is a copy of the styles from https://github.com/mui-org/material-ui/blob/v4.12.3/packages/material-ui/src/SvgIcon/SvgIcon.js#L10
icon: {
fill: "currentColor",
width: "1em",
height: "1em",
display: "inline-block",
fontSize: "1.5rem",
transition: "fill 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms",
flexShrink: 0,
userSelect: "none"
}
});
function CustomSvgIcon({ className, ...other }) {
const classes = useIconStyles();
return (
<TestSvgAsComponent className={clsx(classes.icon, className)} {...other} />
);
}
class SimpleSelect extends React.Component {
state = {
age: "",
name: "hai"
};
handleChange = (event) => {
this.setState({ [event.target.name]: event.target.value });
};
render() {
const { classes } = this.props;
return (
<form className={classes.root} autoComplete="off">
<FormControl className={classes.formControl}>
<InputLabel htmlFor="age-simple">Age</InputLabel>
<Select
value={this.state.age}
onChange={this.handleChange}
inputProps={{
name: "age",
id: "age-simple"
}}
IconComponent={CustomSvgIcon}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
</form>
);
}
}
SimpleSelect.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(SimpleSelect);
Related documentation:
https://material-ui.com/components/icons/#svgicon
Related answer:
Select is not working onClick IconComponent(dropdown-arrow) in react material ui
I need to make a stylized version of material-ui select component.
What i have now is:
import { Select } from '#material-ui/core';
import type { SelectProps } from '#material-ui/core';
import styled from 'styled-components';
const menuProps = {
getContentAnchorEl: null,
anchorOrigin: {
vertical: "bottom",
horizontal: "left",
},
PopoverClasses: {
// pass only classnames
}
}
const StyledSelect = styled(Select)<SelectProps>`
... some styles
`;
const Select: React.FC<SelectProps> = (props) => {
return <StyledSelect MenuProps={menuProps} {...props}/>
};
I need to pass styles(NOT CLASSES) to popover part of Select to make a margin between popover and input.
I tried everything and found only way to pass classes to them.
But I can't use global classes o module classes because of project restrictions, only pass them in js.
Any ideas?
If you use the disablePortal: true menu prop, it will cause the Popover to be a descendant of the Select's root element in the DOM. This allows you to target it like the following:
const Select = styled(MuiSelect)`
.MuiPopover-paper {
margin-top: 3px;
}
`;
Here's a full working example:
import React from "react";
import InputLabel from "#material-ui/core/InputLabel";
import MenuItem from "#material-ui/core/MenuItem";
import MuiFormControl from "#material-ui/core/FormControl";
import MuiSelect from "#material-ui/core/Select";
import styled from "styled-components";
import { StylesProvider } from "#material-ui/core/styles";
const FormControl = styled(MuiFormControl)`
margin: 8px;
min-width: 120px;
`;
const Select = styled(MuiSelect)`
.MuiPopover-paper {
margin-top: 3px;
}
`;
export default function SimpleSelect() {
const [age, setAge] = React.useState("");
const handleChange = event => {
setAge(event.target.value);
};
const menuProps = {
getContentAnchorEl: null,
anchorOrigin: {
vertical: "bottom",
horizontal: "left"
},
disablePortal: true
};
return (
<StylesProvider injectFirst>
<div>
<FormControl>
<InputLabel id="demo-simple-select-label">Age</InputLabel>
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
value={age}
onChange={handleChange}
MenuProps={menuProps}
>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
</div>
</StylesProvider>
);
}
How can I change the color of the label which is showing in grey color? Depending on the theme of the page I have to change the color of the label or even if I remove the override color it should work.
Example remove the default one:
.MuiFormLabel-root {
/* color: rgba(0, 0, 0, 0.54); //default in the browser
}
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles(theme => ({
root: {
"& .MuiFormLabel-root": {
color: "white"
}
}
}));
export default function SelectBox(props) {
const classes = useStyles();
return (
<FormControl
style={{ width: '100%' }}>
<InputLabel shrink className={classes.root}>
{props.label}
</InputLabel>
</FormControl>
)
}
You can pass the classes object and overirde the root which corresponds to .MuiInputLabel-root
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import { FormControl } from "#material-ui/core";
import { InputLabel } from "#material-ui/core";
const useStyles = makeStyles(theme => ({
root: {
color: "red"
}
}));
export default function SelectBox(props) {
const classes = useStyles();
return (
<FormControl style={{ width: "100%" }}>
<InputLabel shrink classes={{ root: classes.root }}>
{props.label}
</InputLabel>
</FormControl>
);
}
To have result like this -
Working sandbox here - https://codesandbox.io/s/update-input-label-color-kzew2?file=/demo.js:0-513