thanks for being here! My question is related to how I can create an 'onChange' property in the Material UI Menu component. When I am using the 'onChange' property of the Select component, I can easily alter my state after the user clicks on it. I would like to create a similar effect, but then using a Menu instead of a Select component. Note that I am using a function inside a hook, which might complicate things.
Below I could show you how an example of how my code looks:
const [sortingMethod, setSortingMethod] = useState(() => sortHighestSummerTemp);
const onSortMethod = (e) => {
setSortingMethod(e.target.value);
};
<FormControl>
<InputLabel shrink>Sort By </InputLabel>{' '}
<Select defaultValue="" onChange={onSortMethod}>
<MenuItem value={() => sortHighestSummerTemp}>☀️ Hottest summers</MenuItem>
<MenuItem value={() => sortLowestWinterTemp}>🥶 Coldest winters</MenuItem>
<MenuItem value={() => sortMostHotDays}>🥵 Most hot days</MenuItem>
</Select>
</FormControl>;
That's my select component in action, which is working. And here is the same Menu, where I don't know how to implement the "onChange":
<FormControl className={classes.formControl}>
<PopupState variant="popover" popupId="demo-popup-menu">
{(popupState) => (
<React.Fragment>
<Button
variant="contained"
color="primary"
startIcon={<SortIcon />}
{...bindTrigger(popupState)}
>
Sort by
</Button>
<Menu
value=""
// onChange={onSortMethod} <-- How to do this? ⚠
{...bindMenu(popupState)}
>
<MenuItem
onClick={popupState.close}
value={() => sortHighestSummerTemp}
>
☀️ Hottest summers
</MenuItem>
<MenuItem
onClick={popupState.close}
value={() => sortLowestWinterTemp}
>
🥶 Coldest winters
</MenuItem>
<MenuItem onClick={popupState.close} value={() => sortMostHotDays}>
🥵 Most hot days
</MenuItem>
</Menu>
</React.Fragment>
)}
</PopupState>
</FormControl>;
I would be blessed if you could explain how to achieve a similar effect with the Menu component!
Thank you for reading.
I think you should do that per MenuItem (at the onClick property). The Menu itself doesn't have that kind of property: Material-UI page
Secondly, I don't like value as a function. I think you can just pass the variable (sortHighestSummerTemp or sortLowestWinterTemp) to a state. React page reference
Related
I have an MUI TextField Select that has optgroups. I already tried a native Select, which didn't allow for the css customization I need for the dropdown menu.
Below is a simplified version of the code:
options = { group1: ['o1','o2','o3'], group2: ['o3','o4','o5'] }
<TextField
select
onChange={(e) => handleChange(e)} // <<< This doesn't work
>
{ options && Object.entries(options).map( ( [k,v] ) => { return (
<Box key={k + 'optgroup'}> // <<< I think this is why. What should this be?
<MenuItem
disabled
data-type='optgroup'
>
{k}
</MenuItem>
v.map( (ov:string,oi:number) => {
return (
<MenuItem
key={ov+oi}
data-type='option'
>
{ov}
</MenuItem>
)
})
</Box>
)})}
</TextField>
The example above has no functionality - the onChange does nothing, I changed it to be an onClick on the MenuItem - but that doesn't close the menu.
Question: What is the correct way to build a non-native MUI Select with grouping?
I have the following material-ui Select component:
<FormControl fullWidth className="attr-foreign-key">
<InputLabel id={field+"-label"}>{catalog.title_singular}</InputLabel>
<Select
labelId={field+"-label"}
id={field}
value={value_name}
onChange={this.handleChange(value_id)}
renderValue={value_name => value_name}
>
<MenuItem value="">
<em>Ninguno</em>
</MenuItem>
{
this.state.choices? this.state.choices.map(choice => <MenuItem value={choice.name}>{choice.name}</MenuItem>): null
}
</Select>
</FormControl>
The problem is that it displays the label of the Select over its content:
It only displays well when the Select has the focus:
But it fails again when it looses it. I haven't found any reference for solving this.
Material ui has a props in Textfield component to transform it to use select. Doing so you wont have the problem and it will be easier for you to use for the same result.
link
Code sample:
<TextField
id="filled-select-currency"
select
label="Select"
value={currency}
onChange={handleChange}
helperText="Please select your currency"
variant="filled"
>
{currencies.map(option => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</TextField>
Hope it helps.
I have been using a Premade React-Bootstrap Typeahead search-bar found here
I am having trouble accessing the child elements from the dropdown. I want to be able to have an Onclick function for the dropdown items, but it doesn't seem like I have access to the children.
Below is the code I have currently, where I use typeahead
<div className="search-bar">
<Typeahead
id="sample"
options= {cities.map((city) => (city))}
labelKey="name"
placeholder="Enter a city"
/>
</div>
How do I get an onclick for these element cities listed?
You can customize menu rendering and behavior by using the renderMenu prop:
<Typeahead
options={options}
renderMenu={(results, menuProps) => (
<Menu {...menuProps}>
{results.map((result, index) => (
<MenuItem
onClick={() => console.log('click!')}
option={result}
position={index}>
{result.label}
</MenuItem>
))}
</Menu>
)}
/>
With the menu items exposed, you're free to add your own onClick handler to each item. Here's a working example.
I am using redux form with material ui. I have an array of form templates that are available to select as options. What I am trying to achieve is to get the selected template back, dispatch an action and then initialize redux form with selected template values. I am unable to call the method on SelectItem component (nothing gets logged to the console). I went through the similar problems and solutions but nothing seemed to work in my case. My code goes like this:
setTemplate = (option) => {
console.log(option);}
{formTemplates && (
<Row>
<StyledFormControl>
<Field name="templates" label="Available templates:" component={SelectField}>
<MenuItem value="" disabled>
Choose template:
</MenuItem>
{formTemplates.map(option => {
return (
<MenuItem value={option._id} onClick={this.setTemplate.bind(this, option)} key={option._id}>
{option._id}
</MenuItem>
);
})}
</Field>
</StyledFormControl>
</Row>
)}
Do you have any idea why this should not work? Thanks
try
onClick={() => this.setTemplate(option).bind(this)}
I am trying to determine if SelectField is expanded or not, i.e. if the dropdown and it's MenuItems are visible.
Currently I use roughly following approach:
<SelectField onClick={() => this.setState({ isExpanded: true })} >
<MenuItem primaryText={
<MenuItemContent onHide={() => this.setState({ isExpanded: false })}} />
}>
</SelectField>
and in MenuItemContent I implement
class MenuItemContent extends React.Component {
componentWillUnmount = () => this.props.onHide()
}
This approach has a drawback, that when you click outside the menu, the componentWillUnmount call is not triggered immidiately, but cca after 200ms, despite the MenuItems are no longer visible.
The Select field menu can be expanded by clicking it, and when is expanded, it will hide either when some menu item is clicked, or user clicks outside the menu.
This is how the SelectField looks when is expanded:
And here is collapsed:
For the better handling of SelectField close event you can use property dropDownMenuProps:
/**
* Object that can handle and override any property of component DropDownMenu.
*/
dropDownMenuProps: PropTypes.object,
By using this prop we can pass to DropDownMenu component onClose prop with handler function, which will be fired instantly after DropDownMenu close (caused by ESC, outside click or item select). Unfortunately DropDownMenu component dont provide similar prop to determine the opening so the only way (without
extending the component) is to follow your approach with onClick event handler.
Here is my working test example:
onSelectClose = () => {
console.log("close")
}
onSelectOpen = () => {
console.log("open")
}
render() {
return (
<MuiThemeProvider>
<div className="App">
<SelectField
floatingLabelText="Frequency"
onClick={this.onSelectOpen}
dropDownMenuProps={{
onClose: this.onSelectClose
}}
value={this.state.value}
onChange={this.handleChange}>
<MenuItem value={1} primaryText="Never" />
<MenuItem value={2} primaryText="Every Night" />
<MenuItem value={3} primaryText="Weeknights" />
<MenuItem value={4} primaryText="Weekends" />
<MenuItem value={5} primaryText="Weekly" />
</SelectField>
</div>
</MuiThemeProvider>
);
}
Detecting if React Material UI Select Field is expanded
The answer is available in Materia-UI Select-API documentation.
Link: https://material-ui.com/api/select/