After i implemented my application, i wanted to style it with Material UI.
When changing from html to Material i started recieving a warning when clicking select item:
index.js:1 Warning: findDOMNode is deprecated in StrictMode. findDOMNode was passed an instance of Transition which is inside StrictMode. Instead, add a ref directly to the element you want to reference.
Initial code:
<label htmlFor="newRole">Role</label>
<select
name="newRole"
id="newRole"
value={newUser.newRole}
onChange={handleChangeNew}
>
<option value="0">Student</option>
<option value="2">Professor</option>
<option value="3">Secretary</option>
</select>
Material UI code:
<InputLabel shrink id="role-lbl"> Role </InputLabel>
<Select
labelId="role-lbl"
name="newRole"
id="newRole"
value={newUser.newRole}
onChange={handleChangeNew}
// displayEmpty
variant="filled"
>
<MenuItem value="0">Student</MenuItem>
<MenuItem value="2">Professor</MenuItem>
<MenuItem value="3">Secretary</MenuItem>
</Select>
That is a little bit strange but I can not reproduce your warning. But as I faced it several times I can give you two advices how to fix it.
(not recommend) Just remove <React.StrictMode> wrapper on your <App />
useRefs. The idea might look like this:
import {InputLabel, MenuItem, Select} from "#material-ui/core";
import {useRef} from "react";
export default function Example3() {
const nodeRef = useRef(null);
function handleChangeNew(){
console.log('changed');
}
return(
<>
<InputLabel shrink id="role-lbl"> Role </InputLabel>
<Select
noderef={nodeRef}
labelId="role-lbl"
id="newRole"
value={newUser.newRole}
onChange={handleChangeNew}
// displayEmpty
variant="filled"
>
<MenuItem value="0" ref={nodeRef}>Student</MenuItem>
<MenuItem value="1" ref={nodeRef}>Professor</MenuItem>
<MenuItem value="2" ref={nodeRef}>Secretary</MenuItem>
</Select>
</>
)
}
Related
In my React app, I am using a MaterialUI Form Control API TextField. In the Select tag, I am firing a method onClick, but it does fire only after first click. I don't have any hidden CSS applied to these tags. Here is the following snippet:
<FormControl style={{ width: '12em', marginTop: '1em' }} variant="outlined">
<InputLabel htmlFor="outlined-age-native-simple">Select Template</InputLabel>
<Select
native
label="Select-Template"
onClick={this.GetTemplates}
>
{templates.length &&
templates.map(x => (
<option
key={x.template_id}
value={JSON.stringify(x.template_content)}
style={{ border: 'solid' }}>
{x.template_name}
</option>
))}
</Select>
</FormControl>
The function:
GetTemplates = e => {
XRayApi.getTemplates(this.getTemplatesApiResponse);
};
I cannot find out the reason at all. Any help on this?
You should use onChange={this.GetTemplates} in your code to get it working. As per the official API docs of material-ui>select, onClick is not available. Now, your code will become
<FormControl style={{ width: '12em', marginTop: '1em' }} variant="outlined">
<InputLabel htmlFor="outlined-age-native-simple">Select Template</InputLabel>
<Select
native
label="Select-Template"
onChange={this.GetTemplates}>
{templates.length &&
templates.map(x => (
<option
key={x.template_id}
value={JSON.stringify(x.template_content)}
style={{ border: 'solid' }}>
{x.template_name}
</option>
))}
</Select>
</FormControl>
Try onChange instead of onClick in Select.
<Select
native
label="Select-Template"
onChange={this.GetTemplates}
>
I'm struggling to override the default padding of the Select component to match the size of my other text fields. I understand that I need to modify nested components but have been unable to find a working solution.
<div className='wifi-chooser-column'>
<TextField
style={{margin: '6px'}}
label='SSID'
variant='outlined'
size='small'
/>
<Select
style={{margin: '6px', padding: '0px'}}
variant='outlined'
value={this.state.security}
onChange={(event) => this.setState({security: event.target.value})}
classes={{
select: {
padding: '10.5px 14px'
}
}}
>
<MenuItem label='security' value='Unsecured'>Unsecured</MenuItem>
<MenuItem value='WEP'>WEP</MenuItem>
<MenuItem value='WPA2'>WPA2</MenuItem>
</Select>
<TextField
style={{margin: '6px'}}
label='Username'
variant='outlined'
size='small'
/>
<TextField
style={{margin: '6px'}}
label='Password'
variant='outlined'
size='small'
/>
Layout issue
According to the doc, there are several ways that we can override the material UI component styles.
If we want to override the padding of the Select components differently and occasionaly, or if this process would not be repeated in the entire project, we can simply use Overriding styles with classes approach. In this way, first we need to create our desired padding for Select component by makeStyles as below:
const useStyles = makeStyles((theme) => ({
rootFirstSelect: {
padding: "4px 0px"
},
rootSecondSelect: {
padding: "10px 80px"
}
}));
and then assign it to the classes prop of the component, by modifying the root element:
const classes = useStyles();
//Other part of the code
return (
//Other part of the code
<Select
classes={{ root: classes.rootFirstSelect }}
//other props
>
//Other part of the code
)
working sandbox example for this method
If we want to override the padding of the Select component for the whole project, Global theme variation would prevent repetition. In this way, we should create a theme by createMuiTheme, as below, and apply our desired changes there:
const theme = createMuiTheme({
overrides: {
MuiSelect: {
select: {
padding: "4px 0px 10px 130px !important"
}
}
}
});
then pass this theme as a prop to the ThemeProvider component which surround the whole project:
<ThemeProvider theme={theme}>
<Demo />
</ThemeProvider>
working example in sandbox
I found an alternative way in the docs, that's easier to use for me: instead of using Select component, I use TextField with "select" props
cf: https://material-ui.com/components/text-fields/#select
<TextField
id="standard-select-currency"
select
label="Select"
value={currency}
onChange={handleChange}
helperText="Please select your currency"
>
{currencies.map((option) => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</TextField>
Which allows you to access TextField props such as margin="none", margin="dense"
I am using react material in react with select component.I want to add first disable option something like “please select item”
Implemented in html like this
<select name="tagging">
<option selected disabled>I'm working</option>
<option value="Option B">Option B</option>
<option value="Option C">Option C</option>
</select>
How I will achieve this using material + react
here is my code
https://codesandbox.io/s/6836mkjx3
<FormControl className={classes.formControl}>
<InputLabel htmlFor="searchCriteria">SEARCH CRITERIA *</InputLabel>
<Select
value={searchCriteria}
onChange={event => handleInput(event, "searchCriteria")}
input={<Input name="searchCriteria" id="searchCriteria" />}
>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
<FormHelperText>Some important helper text</FormHelperText>
</FormControl>
here is select example in material
https://material-ui.com/demos/selects/
https://material-ui.com/demos/selects/#selects
This is what you are looking for
example is given in material ui documentation
You can implement it with
<MenuItem value="">
<em>None</em>
</MenuItem>
for standard material select and with <option value="" /> if you are using "native" material select.
Additionaly you can add disabled prop.
Codesandbox example forked from material-ui docs
use value="" for first option in material select.
<MenuItem selected disabled value="">
<em>None</em>
</MenuItem>
You need a label
import: import InputLabel from '#mui/material/InputLabel';
Component: <InputLabel id="demo-simple-select-disabled-label">Select one</InputLabel>
I want to display like an error with red color unless there is a selected option.
Is there any way to do it.
For setting a required Select field with Material UI, you can do:
class SimpleSelect extends React.PureComponent {
state = {
selected: null,
hasError: false
}
handleChange(value) {
this.setState({ selected: value });
}
handleClick() {
this.setState(state => ({ hasError: !state.selected }));
}
render() {
const { classes } = this.props;
const { selected, hasError } = this.state;
return (
<form className={classes.root} autoComplete="off">
<FormControl className={classes.formControl} error={hasError}>
<InputLabel htmlFor="name">
Name
</InputLabel>
<Select
name="name"
value={selected}
onChange={event => this.handleChange(event.target.value)}
input={<Input id="name" />}
>
<MenuItem value="hai">Hai</MenuItem>
<MenuItem value="olivier">Olivier</MenuItem>
<MenuItem value="kevin">Kevin</MenuItem>
</Select>
{hasError && <FormHelperText>This is required!</FormHelperText>}
</FormControl>
<button type="button" onClick={() => this.handleClick()}>
Submit
</button>
</form>
);
}
}
Working Demo on CodeSandBox
Material UI has other types of Select(native) also where you can just use plain HTML required attribute to mark the element as required.
<FormControl className={classes.formControl} required>
<InputLabel htmlFor="name">Name</InputLabel>
<Select
native
required
value={this.state.name}
onChange={this.handleChange}
inputProps={{
name: 'name',
id: 'name'
}}
>
<option value="" />
<option value={"lala"}>lala</option>
<option value={"lolo"}>lolo</option>
</Select>
</FormControl>
P.S. https://material-ui.com/demos/selects/#native-select
The required prop only works when you wrap your elements inside a <form> element, and you used the submit event to submit the form.
this is not related to react, this is pure HTML.
In MUI v5 (2022), it works like this:
const handleSubmit = (e)=>{
e.preventDefault()
// ...
}
return (
<form onSubmit={handleSubmit}>
<Select required value={val} onChange={handleChange} required>
<MenuItem value="yes">Yes</MenuItem>
<MenuItem value="no">No</MenuItem>
</Select>
<Button type="submit">Submit</Button>
</form>
)
As you can see, it works the same way you think it should work, so what your code should probably be similar to this.
But the required prop only works when you wrap your elements inside a element, and you used the submit event to submit the form.
And if you're using <FormControl>, but the required prop on both elements:
<FormControl required>
<Select required>
// ...
</FormControl>
I have created a Meteor project with ReactJS.
For the Create/Edit page, I use the same page, in text input, I have the following code:
<FormGroup>
<ControlLabel>Province</ControlLabel>
<input
type="text"
className="form-control"
name="province"
ref={province => (this.province = province)}
defaultValue={regs && regs.province}
/>
</FormGroup>
To get the same result.
How can I use name, ref, defaultValue in select-option, checkbox, radio,..etc. like text?
<FormGroup controlId="formControlsSelect">
<ControlLabel>Sex</ControlLabel>
<FormControl componentClass="select" name="sex" ref={sex => (this.sex = sex)} defaultValue={regs && regs.sex}>
<option value="male">Male</option>
<option value="female">Female</option>
</FormControl>
</FormGroup>
Thank you very much to pawel.
I can solve this by changing
<FormControl ref=....> to <FormControl inputRef=...>