Material UI (React): how to style the Input wrapping the Select? - reactjs

I have the following JSX:
<FormControl>
<InputLabel>My label</InputLabel>
<Select>
...
</Select>
</FormControl>
I use the classes prop to style various aspects of the FormControl and Select. The trouble is that the Select component implicitly wraps itself with an Input component, and thus in reality looks something like this:
<FormControl>
<InputLabel>My label</InputLabel>
<Input>
<Select>
...
</Select>
</Input>
</FormControl>
That's where I'm having problems: how can I style the Input that is wrapping the Select? I've looked at the CSS APIs for both Select and FormControl, and neither of them allow you to style that Input.
I know I can add a className to the FormControl and then style it using an external stylesheet, but I want to style it on the component level.
Any ideas?
EDIT:
A snippet of my code (with dummy content), for illustration (was requested):
<FormControl
classes={myClasses.formControl}
>
<InputLabel
htmlFor='country'
classes={myClasses.inputLabel}
>
Select country
</InputLabel>
<Select
value={countryCode}
onChange={onInputChange}
inputProps={{
name: 'countryCode',
id: 'country',
}}
classes={myClasses.select}
>
<MenuItem value='US'>United States</MenuItem>
<MenuItem value='GB'>United Kingdom</MenuItem>
<MenuItem value='FR'>France</MenuItem>
</Select>
</FormControl>

You can do it via standard css import (look at generate code and retrieve the css path) or you can style it using a wrapper and styling it with styled-components. A snippet with a real case would be useful for me to be more specific.

Okay, I've found the solution.
To style the wrapping Input component, you need to explicitly define it in the Select's input prop, and then pass the classes prop to that Input.
Here is an example:
<Select
input={
<Input
classes={myClasses.input}
/>
}
>
...
</Select>

Related

How to fix Material-UI Select w/ MenuItem where MenuItem being rendered horizontally?

I've been playing with Material-UI with React/Next.js and I'm running across a weird and persistent bug. I can't get the <Select> to render a regular vertical dropdown menu. How do I get the <MenuItem>s to render vertically?
I searched the docs and can't find anything. It's also worth noting my code is pretty much the same as the example:
render (
<div>
<FormControl
fullWidth
style={{
paddingBottom: formError
? `${paddingBeneathFormControls}px`
: `${paddingBeneathFormControls + 22}px`,
}}
>
<InputLabel id="demo-simple-select-label">Age</InputLabel>
<Select
className="test"
labelId="demo-simple-select-label"
label="Age"
value={10}
>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
{formError && (
<FormHelperText error>
Please enter a valid value.
</FormHelperText>
)}
</FormControl>
</div>
)
There may be some unexpected side-effects for others, but I found a solution to my problem. I was using #mui/material library, which I figured was the more modern version - they say NASA, Netflix, Spotify and others use this library. I simply changed my import to #material-ui/core, which exposes the same elements I was using (Select, MenuItem, FormControl, FormHelperText, InputLabel, TextField). I'm not entirely sure where these two libraries differ but in my case simply switching that made all my code work.
It's worth noting that using both adds some conflicting styling behavior - I tried at first to only borrow the Select and MenuItem components from #material-ui/core, but when I imported that library it broke the component styling for #mui/material components.

Make tags on Select editable

I'm using Select component from antd Design in my React app with Tag mode, and I want the tags inside that Select to be editable when the user double click on it
Any idea how can I do that?
Here is the code so far:
<Select
showSearch={false}
mode="tags"
onChange={handleChange}
tokenSeparators={[',']}
value={Tags}
>
{children}
</Select>
Check out React Synthetic Event : https://reactjs.org/docs/events.html#mouse-events
<option onDoubleClick={yourFunctionForDoubleClick} value={option.value}>{option.label}</option>
yourFunctionForDoubleClick =(event)=> { your logic here, then setState({yourState: event.target.value})}

Material-ui's Menu Item not working with a Select within a redux-form Field (redux form 8.2)

I'm trying to create a select (dropdown) using Material-UI within a redux-form. There's an example for using M-UI's selects within a redux form on their website.
I'd like to do the same type of example except using Material UI's MenuItem's instead of the option tags used in the example.
It seems as though simply replacing the options with MenuItems does not work, and the MenuItems do not appear under the children for the select field. I have gotten this to work with options:
Here is the renderSelectField used to create the select component. This is working:
renderSelectField = ({ input, label, meta: { touched, error }, children, ...custom }) => (
<FormControl className={this.props.classes.formControl} error={touched && error}>
<InputLabel>{label}</InputLabel>
<Select
native
{...input}
{...custom}
>
{children}
</Select>
{this.renderFormHelper({ touched, error })}
</FormControl>
)
And here is the render:
render() {
return (
<div>
<form onSubmit={this.props.handleSubmit(this.props.submitForm)}>
<Field name={"sheetType"} component={this.renderSelectField} label={"Sheet Type"}>
<MenuItem value={"basic"} primaryText={"Basic"}>Basic</MenuItem>
<MenuItem value={"advanced"} primaryText={"Advanced"}>Advanced</MenuItem>
</Field>
<Button onClick={this.props.onCancel}>Cancel</Button>
<Button type="submit" color={"secondary"}>Next</Button>
</form>
</div>
)
}
I expect there to be two dropdown menu items passed in as the children of MenuItem, but i believe there needs to be some property passed into MenuItem itself.
Replacing menu item with option tags work.
You are mixing between simple Select and native Select. If you going to use native change <MenuItem> to <option> otherwise just remove native property.
Native pattern:
<Select native>
<option value="item">item</option>
</Select>
Simple Select pattern:
<Select>
<MenuItem value="item">item</MenuItem>
</Select>

how to set helperText in react-select

I am using react-select and TextField Material-UI.
Is there possibility to set helperText (small text below component) in react-select like it is made in TextField?
Thank You for help in advance.
P.S. I do not think my question is duplication of this question. The other post is about how to custom component which is a part of react-select, I want to add an option that react-select doesnt have.
TextField is mainly a convenience wrapper around several lower-level components including FormHelperText.
Here is the Autocomplete demo in the Material-UI documentation using react-select: https://material-ui.com/demos/autocomplete/#react-select
Here is a modified version of that demo using FormHelperText: https://codesandbox.io/s/rynvn8po5p
Here's the relevant snippet from that code:
<Select
classes={classes}
styles={selectStyles}
options={suggestions}
components={components}
value={this.state.single}
onChange={this.handleChange("single")}
placeholder="Search a country (start with a)"
isClearable
/>
<FormHelperText>Here's my helper text</FormHelperText>
The Material-UI demos for Select also show many examples of using FormHelperText without using TextField: https://material-ui.com/demos/selects/#simple-select
Here is the API documentation for FormHelperText: https://material-ui.com/api/form-helper-text/
Do you mean placeholder?
I think You can set this way:
const MyComponent = () => (
<Select placeholder="Select..." options={options} />
)
But if you want the same look why do you use controls from different libraries. I think you can use FormHelperText with Select from Material-Ui. So you might as well this select instead of react-select.
<FormControl className={classes.formControl}>
<InputLabel shrink htmlFor="age-native-label-placeholder">
Age
</InputLabel>
<NativeSelect
value={this.state.age}
onChange={this.handleChange('age')}
input={<Input name="age" id="age-native-label-placeholder" />}
>
<option value="">None</option>
<option value={10}>Ten</option>
<option value={20}>Twenty</option>
<option value={30}>Thirty</option>
</NativeSelect>
<FormHelperText>Label + placeholder</FormHelperText>
</FormControl>

Material-UI: Native Select when using Dark theme on Windows Browsers has white text on white background

When using the Native Select from Material-UI if you use the dark theme then the select dropdown has white text on a white background.
This is seen on the component demo page too when in dark mode:
Can you change the dropdown background color without changing the actual select background color?
Edit: This has been logged as an issue: https://github.com/mui-org/material-ui/issues/14337
UPDATE As of version 3.9.2, this issue has been fixed in Material-UI so the workaround below is no longer necessary.
This should probably be fixed in Material-UI, but you can fix it in a particular use case with the following:
Use the theme to specify the option background color (see How to change select box option background color?):
const styles = theme => ({
select: {
"& option": {
background: theme.palette.background.paper
}
}
});
And then use that class on the select:
<Select native className={classes.select}>
Here's a modified version of the demo using this:
It obviously something that should fixed in the package.
However, I found out that it happends only when using native <option> tag. This code if from the problematic demo of theirs:
<Select
native
value={this.state.age}
onChange={this.handleChange('age')}
inputProps={{
name: 'age',
id: 'age-native-simple',
}}
>
<option value="" />
<option value={10}>Ten</option>
<option value={20}>Twenty</option>
<option value={30}>Thirty</option>
</Select>
So you have two options:
You can style the option with css and ovveride the background or the fontcolor to anything you want.
You can use another component in material-ui that works well with inverted situations, which they used in another demo. (Using MenuItem), like this:
<Select
multiple
value={this.state.name}
onChange={this.handleChange}
input={<Input id="select-multiple-checkbox" />}
renderValue={selected => selected.join(', ')}
MenuProps={MenuProps}
>
{names.map(name => (
<MenuItem key={name} value={name}>
<ListItemText primary={name} />
</MenuItem>
))}
</Select>
Watch full example here. (Taken from material-ui demo page)

Resources