How to pass variable to MUI styled function in ReactJS - reactjs

How can I pass variable to conditionally change styles properties while using MUI styled function? I want to achieve this: borderColor: darkMode ? 'white' : 'black'
const StyledSelect = styled(Select)(() => ({
"& fieldset": {
borderColor: 'dark',
}
}));
function BasicSelect() {
const { darkMode }= useSelector((state: {options: {darkMode: boolean}})=>state.options)
const [age, setAge] = React.useState('');
const handleChange = (event: SelectChangeEvent) => {
setAge(event.target.value as string);
};
return (
<FormControl fullWidth>
<InputLabel id="demo-simple-select-label">Age</InputLabel>
<StyledSelect
labelId="demo-simple-select-label"
id="demo-simple-select"
value={age}
label="Age"
onChange={handleChange}
>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
);
}
One of the options that works is to make function and pass it to sx prop like this, but I wonder if it is possible to pass variable directly to styled function
const selectstyles = (darkMode) => ({
"& fieldset": {
borderColor: darkMode ? 'white' : 'black'
}
})
<StyledSelect sx={selectStyles(darkMode)} ...></StyledSelect>

The same question was asked here: https://stackoverflow.com/a/69341672/8972840
This will help you pass props through the styled() function.

Related

Mui select - change background color once a menuItem is selected

I have a Mui Select with different menu items. I want to be able to change the background color of the select once a user has chosen a menu item.
This is one of my selects with the menu items:
<p className="text-md font-nunito font-medium">Role</p>
<FormControl>
<Select
displayEmpty
variant="outlined"
id="role"
name="role"
className="border text-white"
sx={{
bgColor: '#393939',
color: 'white',
'& .MuiSelect-iconOutlined': {
color: '#393939',
},
}}
value={role}
onChange={(event) => {
handleChange(event);
handleRoleSwitch(event);
}}
onBlur={handleBlur('role')}
MenuProps={{
PaperProps: {
sx: {
bgcolor: '#393939',
'& .MuiMenuItem-root': {
padding: 2,
color: 'white',
},
},
},
}}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem className="text-white" value="admin">
Admin
</MenuItem>
<MenuItem className="text-white" value="user">
User
</MenuItem>
<MenuItem className="text-white" value="viewer">
Viewer
</MenuItem>
</Select>
</FormControl>
How about using a useState variable for representing the bgColor that changes when clicking a menu item?
Here is a quick example on how you could do it.
const [bgColorValue, setBgColorValue] = useState('#393939')
const handleBgColorChange = (newValue) => {
setBgColorValue(newValue)
}
<Select
displayEmpty
variant="outlined"
id="role"
name="role"
className="border text-white"
sx={{
bgColor: '#393939',
color: 'white',
'& .MuiSelect-iconOutlined': {
color: '#393939',
},
}}
value={role}
onChange={(event) => {
handleChange(event);
handleRoleSwitch(event);
}}
onBlur={handleBlur('role')}
MenuProps={{
PaperProps: {
sx: {
bgcolor: bgColorValue,
'& .MuiMenuItem-root': {
padding: 2,
color: 'white',
},
},
},
}}
>
```
And then just use the onClick={() => handleBgColorChange('#404040')} where you want the new bgValue to be set. Obviously, i just used #404040 as a example. Hope this helps in some sort of way.
You can create a variable to set if a selection happened using useState. Then control it using the onChange of the Select.
Have a look at the code below and in this working codesandbox
Here is a working codesandbox with your code.
I have used styled-components in both.
import * as React from "react";
import Box from "#mui/material/Box";
import InputLabel from "#mui/material/InputLabel";
import MenuItem from "#mui/material/MenuItem";
import FormControl from "#mui/material/FormControl";
import Select, { SelectChangeEvent } from "#mui/material/Select";
import styled from "#emotion/styled";
export interface StyledSelectProps {
isSelected: boolean;
}
const StyledSelect = styled(Select)`
background: ${({ isSelected }: StyledSelectProps) =>
isSelected ? "#f38713" : "white"};
`;
export default function BasicSelect() {
const [age, setAge] = React.useState("");
const [itemSelected, setItemSelected] = React.useState(false);
const handleChange = (event: SelectChangeEvent) => {
setAge(event.target.value as string);
setItemSelected(true);
};
return (
<Box sx={{ minWidth: 120 }}>
<FormControl fullWidth>
<InputLabel id="demo-simple-select-label">Age</InputLabel>
<StyledSelect
labelId="demo-simple-select-label"
id="demo-simple-select"
value={age}
label="Age"
onChange={handleChange}
isSelected={itemSelected}
>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</StyledSelect>
</FormControl>
</Box>
);
}

Why my 'Select' components in react are synchronized together?

I am currently using materialui to create a submission page. I have created two 'Select' components for the page, and there is a problem that if I choose an option from the second 'Select' component, the option from the first 'Select' component will be refreshed. I was thinking there is something wrong with the 'onChange', yet I have no idea about the cause for this problem. I want to select all the options from the 'Select' components before submitting the data at once.
Also, is there a way to disable the second 'Select' components before entering an option other than 'None' in the first 'Select' components, and enable it after a valid option has been entered?
Thank you very much for your time and help!
import React, { Component } from 'react';
import { Form, Field } from 'react-final-form';
import { OnChange } from 'react-final-form-listeners';
import { makeStyles, InputLabel, FormControl, Typography, Paper, Link, Grid, Button, CssBaseline, MenuItem, TextField, Select, Box, FormHelperText} from '#material-ui/core';
const useStyples = makeStyles((theme) => ({
formControl: {
margin: theme.spacing(2),
minWidth: 400
},
typo1: {
padding: 30,
margin: 'auto',
maxWidth: 600
},
typo2: {
padding: 0,
margin: 'auto',
maxWidth: 600
},
}))
export default function CreatePage() {
const classes = useStyples()
const [value, setValue] = React.useState('')
const handleChange = (event) => {
setValue(event.target.value)
}
return (
<div>
<Typography variant='h4' align='center' component='h1' gutterBottom className={classes.typo1}>
Data Submission Form
</Typography>
<Typography variant='h5' align='center' component='h2' gutterBottom className={classes.typo2}>
Material-UI
</Typography>
<Box display='flex' flexDirection='row'>
<Box>
<FormControl required variant='filled' className={classes.formControl}>
<InputLabel shrink>Defect</InputLabel>
<Select
labelId='defect-select1'
id='defect-select1'
value={value}
displayEmpty
onChange={handleChange}>
<MenuItem value=''>None</MenuItem>
<MenuItem value={'Crack'}>Crack</MenuItem>
<MenuItem value={'Scratch'}>Scratch</MenuItem>
<MenuItem value={'Rough Surface'}>Rough Surface</MenuItem>
<MenuItem value={'Spalling'}>Spalling</MenuItem>
</Select>
<FormHelperText>Select Defect for Position 1 - Required</FormHelperText>
</FormControl>
</Box>
<Box>
<FormControl required variant='filled' className={classes.formControl}>
<InputLabel shrink>Tool</InputLabel>
<Select
labelId='tool1'
id='tool1'
displayEmpty
value={value}
onChange={handleChange}>
<MenuItem value=''>None</MenuItem>
<MenuItem value={'Tool 1'}>Tool 1</MenuItem>
<MenuItem value={'Tool 2'}>Tool 2</MenuItem>
<MenuItem value={'Tool 3'}>Tool 3</MenuItem>
<MenuItem value={'Tool 4'}>Tool 4</MenuItem>
</Select>
<FormHelperText>Select Tool Decision for Position 1 - Required</FormHelperText>
</FormControl>
</Box>
</Box>
</div>
);
}
I would be glad if someone can tell me the root cause for the problem. An additon of a solution for my question would be better!
Well, it seems that you only have 1 value :
const [value, setValue] = React.useState('')
And although you have duplicated the <Select /> component you didn't duplicate the value...
You'll need a second "value" and a second handleChange which will update that second value
const [value2, setValue2] = React.useState('');
const handleChange2 = (event) => {
setValue2(event.target.value)
}

Matrial UI change border of outlined select

I want to change the default outline color of the Select component in Material UI.
This is what I've tried but did not work:
const useStyles = makeStyles(theme => ({
formControl: {
margin: theme.spacing(1),
minWidth: 120,
borderColor: "green",
},
selectEmpty: {
marginTop: theme.spacing(2)
},
outlined: {
'&:before': {
borderColor: "green",
},
'&:after': {
borderColor: "green",
}
},
}));
export default function SimpleSelect() {
const classes = useStyles();
const [age, setAge] = React.useState("");
const handleChange = event => {
setAge(event.target.value);
};
return (
<div>
<FormControl variant="outlined" className={classes.formControl}>
<InputLabel id="demo-simple-select-outlined-label">Age</InputLabel>
<Select
labelId="demo-simple-select-outlined-label"
id="demo-simple-select-outlined"
value={age}
onChange={handleChange}
label="Age"
className={classes.outlined}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
</div>
);
}
Thank you in advance for the help!
P.S. This is how it looks when focused/selected
Try with deep nesting or with important.
borderColor: "green !important",

Showing a default value for a select control using react and material-ui control

I am working on a react page using material-ui. I am retrieving data
from the database to populate my select control.
I want to be able to have a default value like "Select the value". The section highlighted in yellow is just blank.
How can I achieve this? An image of what exist is attached.
<FormControl id="ron" className="form-control">
<InputLabel htmlFor="productDescription" shrink>Product Code/Description</InputLabel>
<Select
value={this.state.productCode}
onChange={this.handleChangeProductCode}
name='productcode'
>
<MenuItem value="">
select the value
</MenuItem>
{this.dataForProductCodeControl()}
</Select>
</FormControl>
dataForProductCodeControl() {
if(this.props.groupedData != undefined){
return this.props.groupedData.map((dt, i) => {
return (
<MenuItem key={i} value={dt.productCode}>
{dt.productCode} | {dt.productDescription}
</MenuItem>
);
});
}
}
You need to specify the displayEmpty prop on the Select.
Here's a working example:
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 FormControl from "#material-ui/core/FormControl";
import Select from "#material-ui/core/Select";
const useStyles = makeStyles(theme => ({
root: {
display: "flex",
flexWrap: "wrap"
},
formControl: {
margin: theme.spacing(1),
minWidth: 120
},
selectEmpty: {
marginTop: theme.spacing(2)
}
}));
export default function SimpleSelect() {
const classes = useStyles();
const [values, setValues] = React.useState({
age: ""
});
function handleChange(event) {
setValues(oldValues => ({
...oldValues,
[event.target.name]: event.target.value
}));
}
return (
<form className={classes.root} autoComplete="off">
<FormControl className={classes.formControl}>
<InputLabel htmlFor="age-simple" shrink>
Age
</InputLabel>
<Select
value={values.age}
displayEmpty
onChange={handleChange}
inputProps={{
name: "age",
id: "age-simple"
}}
>
<MenuItem value={""}>Select Age</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
</form>
);
}
You can add a disabled valueless item like this:
<MenuItem value="" disabled>
Placeholder
</MenuItem>
But the item will be displayed as an option. See https://material-ui.com/components/selects/#simple-select

MaterialUI TextField select with text-tranform

I've got the following code where I try to capitalize the values shown as labels inside MenuItem but does not apply the text transformation. Any ideas?
const values = ['some value', 'some value 2'];
<TextField
id="status"
name="status"
select
label="Status"
onChange={this.handleSearch}
value={filter.status}
className={classes.textField}
>
{campaignStatus.map(status => (
<MenuItem key={status} value={status} style={{ textTransform: "capitalize" }}>
{status}
</MenuItem>
))}
</TextField>
this is because material ui has their own system of overriding styles, you have to use this syntax
import { makeStyles } from "#material-ui/core/styles";
const Function = props => {
const useStyles = makeStyles(theme => ({
center: {
textTransform: "capitalize"
}
}));
const classes = useStyles();
const values = ["some value", "some value 2"];
return (
<TextField
id="status"
name="status"
select
label="Status"
onChange={this.handleSearch}
value={filter.status}
className={classes.textField}
>
{campaignStatus.map(status => (
<MenuItem key={status} value={status} className={classes.center}>
{status}
</MenuItem>
))}
</TextField>
);
};

Resources