How to use checkboxes in a nested MenuItem - checkbox

I want to create a checkbox which has three nested elements inside and each of these elements shall contain a list with checkboxes. My problem is that whenever the user clicks on one of the checkboxes, it doesn't get checked, but the menu gets closed.
Also, I can't figure out how to create a scrollbar inside one of the nested lists. At least not the proper way. My workaround was to wrap a Menu with the property maxHeight around the MenuItems, but I don't think that is the proper way. I tried nearly all props I can think of (menuListStyle, listStyle, nestedListStyle, ...), but nothing worked.
Here is my code with my last tries:
import React from 'react';
import IconMenu from 'material-ui/IconMenu';
import MenuItem from 'material-ui/MenuItem';
import IconButton from 'material-ui/IconButton';
import Divider from 'material-ui/Divider';
import ArrowDropRight from 'material-ui/svg-icons/navigation-arrow-drop-right';
import MoreVertIcon from 'material-ui/svg-icons/navigation/more-vert';
import Checkbox from 'material-ui/Checkbox';
import Menu from 'material-ui/Menu';
const UserPermissionButton = () => (
<IconMenu
iconButtonElement={<IconButton><MoreVertIcon /></IconButton>}
anchorOrigin={{horizontal: 'left', vertical: 'top'}}
targetOrigin={{horizontal: 'left', vertical: 'top'}}
>
<MenuItem
primaryText="Permissions"
rightIcon={<ArrowDropRight />}
menuItems={[
<Checkbox label="Admin" />,
<Divider />,
<Checkbox label="Billing" />,
<Checkbox label="Marketplace" />,
<Checkbox label="Usercontrol" />,
]}
/>
<MenuItem
primaryText="Access Groups"
rightIcon={<ArrowDropRight />}
style={{maxHeight: 150, overflow: 'auto'}}
menuItems={[
<MenuItem key={1} primaryText="Child 1" />,
<MenuItem key={2} primaryText="Child 2" />,
<MenuItem key={3} primaryText="Child 3" />,
<MenuItem key={4} primaryText="Child 4" />,
<MenuItem key={5} primaryText="Child 5" />,
<MenuItem key={6} primaryText="Child 6" />,
<MenuItem key={7} primaryText="Child 7" />,
<MenuItem key={8} primaryText="Child 8" />,
]}
/>
<MenuItem
primaryText="Apps"
rightIcon={<ArrowDropRight />}
menuItems={[
<Menu maxHeight={200}>
<Checkbox label="App" />
<Checkbox label="App" />
<Checkbox label="App" />
<Checkbox label="App" />
<Checkbox label="App" />
<Checkbox label="App" />
<Checkbox label="App" />
<Checkbox label="App" />
<Checkbox label="App" />
</Menu>
]}
/>
</IconMenu>
);
export default UserPermissionButton;
UPDATE:
The code has changed to this:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import IconMenu from 'material-ui/IconMenu';
import MenuItem from 'material-ui/MenuItem';
import IconButton from 'material-ui/IconButton';
import Divider from 'material-ui/Divider';
import ArrowDropRight from 'material-ui/svg-icons/navigation-arrow-drop-right';
import MoreVertIcon from 'material-ui/svg-icons/navigation/more-vert';
import Checkbox from 'material-ui/Checkbox';
import Menu from 'material-ui/Menu';
class UserPermissionButton extends Component {
render() {
return(
<IconMenu
iconButtonElement={<IconButton><MoreVertIcon /></IconButton>}
anchorOrigin={{horizontal: 'left', vertical: 'top'}}
targetOrigin={{horizontal: 'left', vertical: 'top'}}
>
<MenuItem
primaryText="Permissions"
rightIcon={<ArrowDropRight />}
menuItems={[
<Checkbox label="Admin" />,
<Divider />,
<Checkbox label="Billing" />,
<Checkbox label="Marketplace" />,
<Checkbox label="Usercontrol" />,
]}
/>
<MenuItem
primaryText="Access Groups"
rightIcon={<ArrowDropRight />}
style={{maxHeight: 150, overflow: 'auto'}}
menuItems={[
<MenuItem key={1} primaryText="Child 1" />,
<MenuItem key={2} primaryText="Child 2" />,
<MenuItem key={3} primaryText="Child 3" />,
<MenuItem key={4} primaryText="Child 4" />,
<MenuItem key={5} primaryText="Child 5" />,
<MenuItem key={6} primaryText="Child 6" />,
<MenuItem key={7} primaryText="Child 7" />,
<MenuItem key={8} primaryText="Child 8" />,
]}
/>
<MenuItem
primaryText="Apps"
rightIcon={<ArrowDropRight />}
menuItems={[
<Menu maxHeight={200}>
{this.props.products.products.map(
product => <Checkbox key={product.id} label={product.name} />
)}
</Menu>
]}
/>
</IconMenu>
);
}
}
function mapStateToProps({products}) {
return {products}
}
export default connect(mapStateToProps)(UserPermissionButton);

You can do this. Basically, using state, you have complete control over when to show the menuitems.
<MenuItem
onTouchTap={() => {
this.setState({ menuOpen: !this.state.menuOpen })
}}
primaryText="Permissions"
rightIcon={<ArrowDropRight />}
/>
{this.state.menuOpen ? (
<Menu maxHeight={200}>
<Checkbox label="App" />
<Checkbox label="App" />
<Checkbox label="App" />
<Checkbox label="App" />
<Checkbox label="App" />
<Checkbox label="App" />
<Checkbox label="App" />
<Checkbox label="App" />
<Checkbox label="App" />
</Menu>): null}
In other words, your component will now have state as follows:
const UserPermissionButton = React.createClass({
getInitialState() {
menuOpen: false
},
render () {
<div>
<IconMenu
iconButtonElement={<IconButton><MoreVertIcon /></IconButton>}
anchorOrigin={{horizontal: 'left', vertical: 'top'}}
targetOrigin={{horizontal: 'left', vertical: 'top'}}
>
<MenuItem
primaryText="Permissions"
rightIcon={<ArrowDropRight />}
onTouchTap={() => {
this.setState({ menuOpen: !this.state.menuOpen })
}}
/>
</IconMenu>
{this.state.openMenu ? (
<div>
<Checkbox label="Admin" />,
<Divider />,
<Checkbox label="Billing" />,
<Checkbox label="Marketplace" />,
<Checkbox label="Usercontrol" />,
</div>
): null}
</div>
}
});

Related

Button opacity doesn't work. How i can replace it

Program can't execute.
My XAML:
<ToolBar x:Name="toolBar1" DockPanel.Dock="Top" >
<Button x:Name="cut2" ToolTip="Cut" >
<Image Source="img/cut.png" Stretch="None" IsEnabledChanged="save2_IsEnabledChanged" />
</Button>
<Button x:Name="copy2" ToolTip="Copy" >
<Image Source="img/copy.png" Stretch="None" IsEnabledChanged="save2_IsEnabledChanged" />
</Button>
<Button x:Name="paste2" Command="ApplicationCommands.Paste" ToolTip="Paste" IsEnabledChanged="save2_IsEnabledChanged" >
<Image Source="img/paste.png" Stretch="None" />
</Button>
</ToolBar>
My cs:
private void save2_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
{
Button b = sender as Button;
b.Opacity = b.IsEnabled ? 1 : 0.5;
}
The problem in Opacity. It's just doesn't work.

Material UI - trying to put paper around columns

I am new to material ui and I am getting a bit caught up in its nuances.
I have two columns of fields and I would like to put a single paper border around the columns without messing up the spacing. I also want the paper to be underneath the title. I have the layout as I want it here.
Where do I add the paper? I've seen simple examples where there is just text - when I add paper here it messes up the spacing.
<form className={classes.container} noValidate autoComplete="off">
<Grid container direction="row">
<Grid item xs />
<Grid item >
<Typography variant="h2" className={classes.title} >Some title</Typography>
</Grid>
<Grid item xs />
</Grid>
<Grid container spacing={2} direction="row">
<Grid item xs />
<Grid item xs={4}>
<Grid container>
<TextField
id="first-name"
label="First Name"
className={classes.textField}
value={this.state.firstName}
onChange={this.handleChange("firstName")}
margin="normal"
/>
<TextField
id="last-name"
label="Last Name"
className={classes.textField}
value={this.state.lastName}
onChange={this.handleChange("lastName")}
margin="normal"
/>
</Grid>
</Grid>
<Grid item xs={4}>
<Grid container>
<TextField
id="address-street"
label="Street Address"
className={classes.textField}
value={this.state.street}
onChange={this.handleChange("street")}
margin="normal"
/>
<TextField
id="address-city"
label="City"
className={classes.textField}
value={this.state.city}
onChange={this.handleChange("city")}
margin="normal"
/>
</Grid>
</Grid>
<Grid item xs />
</Grid>
</form>
I played around with it a bit more and ultimately got it close to what I was aiming for. I think I over-thought it a bit - I wanted to us grid spacing in the outer grid but ultimately I just set max width and took care of it that way. Sandbox updated with final version.
Did you mean a divider line between the first column and the second?
If that is the case then add <Divider/> between the two <Grid container> component it will add a single line to separate the two columns.
Here is what I did,
TextFields.js
import React from "react";
import PropTypes from "prop-types";
import Grid from '#material-ui/core/Grid';
import Divider from '#material-ui/core/Divider';
import Typography from '#material-ui/core/Typography';
import { withStyles } from "#material-ui/core/styles";
import TextField from "#material-ui/core/TextField";
const styles = theme => ({
textField: {
marginLeft: theme.spacing.unit,
marginRight: theme.spacing.unit
}
});
class TextFields extends React.Component {
state = {
firstName: "",
lastName: "",
street: "",
city: ""
};
handleChange = name => event => {
this.setState({ [name]: event.target.value });
};
render() {
const { classes } = this.props;
return (
<form className={classes.container} noValidate autoComplete="off">
<Grid container direction="row">
<Grid item xs />
<Grid item >
<Typography variant="h2" className={classes.title} >Some title</Typography>
</Grid>
<Grid item xs />
</Grid>
<Divider variant="middle" />
<Grid container spacing={2} direction="row">
<Grid item xs />
<Grid item xs={4}>
<Grid container>
<TextField
id="first-name"
label="First Name"
className={classes.textField}
value={this.state.firstName}
onChange={this.handleChange("firstName")}
margin="normal"
/>
<TextField
id="last-name"
label="Last Name"
className={classes.textField}
value={this.state.lastName}
onChange={this.handleChange("lastName")}
margin="normal"
/>
</Grid>
</Grid>
<Grid item xs={4}>
<Grid container>
<TextField
id="address-street"
label="Street Address"
className={classes.textField}
value={this.state.street}
onChange={this.handleChange("street")}
margin="normal"
/>
<TextField
id="address-city"
label="City"
className={classes.textField}
value={this.state.city}
onChange={this.handleChange("city")}
margin="normal"
/>
</Grid>
</Grid>
<Grid item xs />
</Grid>
</form>
);
}
}
TextFields.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(TextFields);
I just added the Material UI Divider component between the two container Grids you can control its width by using variant props or by using css styles.
But if you meant paper border as Paper component, you can still add it like this code below.
TextFields.js
import React from "react";
import PropTypes from "prop-types";
import Grid from '#material-ui/core/Grid';
import Paper from '#material-ui/core/Paper';
import Typography from '#material-ui/core/Typography';
import { withStyles } from "#material-ui/core/styles";
import TextField from "#material-ui/core/TextField";
const styles = theme => ({
textField: {
marginLeft: theme.spacing.unit,
marginRight: theme.spacing.unit
}
});
class TextFields extends React.Component {
state = {
firstName: "",
lastName: "",
street: "",
city: ""
};
handleChange = name => event => {
this.setState({ [name]: event.target.value });
};
render() {
const { classes } = this.props;
return (
<form className={classes.container} noValidate autoComplete="off">
<Grid container direction="row">
<Grid item xs />
<Grid item >
<Typography variant="h2" className={classes.title} >Some title</Typography>
</Grid>
<Grid item xs />
</Grid>
<Paper>x</Paper>
<Grid container spacing={2} direction="row">
<Grid item xs />
<Grid item xs={4}>
<Grid container>
<TextField
id="first-name"
label="First Name"
className={classes.textField}
value={this.state.firstName}
onChange={this.handleChange("firstName")}
margin="normal"
/>
<TextField
id="last-name"
label="Last Name"
className={classes.textField}
value={this.state.lastName}
onChange={this.handleChange("lastName")}
margin="normal"
/>
</Grid>
</Grid>
<Grid item xs={4}>
<Grid container>
<TextField
id="address-street"
label="Street Address"
className={classes.textField}
value={this.state.street}
onChange={this.handleChange("street")}
margin="normal"
/>
<TextField
id="address-city"
label="City"
className={classes.textField}
value={this.state.city}
onChange={this.handleChange("city")}
margin="normal"
/>
</Grid>
</Grid>
<Grid item xs />
</Grid>
</form>
);
}
}
TextFields.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(TextFields);
You can control its height & width by css styles too.

REACT, hiden element overlays parent element when displayed

I have a react component A, that contains more B components generated in A component based on server response using map function. Every B component has a calendar component that needs to show/hide. When calendar component shows it overlays the parent component.
If I put a B component raw, it works perfectly, so I don't think that css is wrong.
When I exam the rendered HTML, the appened calendar is at right place in DOM.
Whad did I wrong.
My A component:
class OffersDesktop extends OffersBase<WithStyles<typeof styles>>
{
render()
{
const css = this.props.classes;
const offers:BookingOffersResponse[] = this.state.offers;
const selectionPalens = offers.map
(
(offer: BookingOffersResponse, index: number) =>
{
return <SelectedPanel offer={offer} key={index + 1} />
}
);
const canContinue: boolean = this.store.state.selectedOffer.OfferID !== '';
const continueButon: JSX.Element = <BlueButton enable={!canContinue} text="Continue" onClick={this.continue}/>;
const Body = () =>
<StackPanel className={css.root} orientation="vertical" centerHorizontally centerVertically>
<Header />
<StackPanel className={css.container} orientation="vertical">
<StackPanel {...dockLeft}>
<HorizontalLinearStepper step={this.props.step} />
</StackPanel>
<StackPanel {...dockLeft} centerVertically className={css.titleContainer}>
<LocalOffer fontSize="large" className={css.icon} />
<span className={css.title}>Offers</span>
</StackPanel>
<StackPanel orientation="horizontal" centerHorizontally>
<StackPanel orientation="vertical" {...dockLeft}>
<StackPanel centerHorizontally centerVertically orientation="vertical">
<SelectedPanel offer={{} as any} key={0} />
<CircleLoader css={css.spinner}
sizeUnit={'px'}
size={100}
color={'#123abc'}
loading={this.state.isDataLoaded}
/>
</StackPanel>
{!this.state.isDataLoaded && selectionPalens}
<StackPanel centerHorizontally centerVertically>
<YearRoundPanel onClick={ this.yearRoundHandler } />
</StackPanel>
</StackPanel>
<StackPanel orientation="vertical" className={css.rightContainer}>
<StackPanel className={css.continueContainer} orientation="vertical" centerHorizontally centerVertically>
<StackPanel className={css.continueButton}>{continueButon}</StackPanel>
<Typography className={css.continueContainerText} variant="subtitle1">Book now with $25 deposit</Typography>
</StackPanel>
<SearchParameters searchParameters={this.state.appState.searchParameters}/>
</StackPanel>
</StackPanel>
</StackPanel>
<StackPanel className={css.footer} {...dockBottom} centerHorizontally><Footer /></StackPanel>
</StackPanel>
return Body();
}
B component
class SelectedPanel extends Connected<typeof React.Component, IProps & WithStyles<typeof styles>, IState, AppStore>(React.Component)
{
constructor(props: IProps & WithStyles<typeof styles>)
{
super(props);
this.state =
{
showCalendar: false,
appState: this.store.state
}
}
showCalnedarHandler = (event: React.MouseEvent<HTMLElement, MouseEvent>) : void =>
{
event.preventDefault();
this.setState
({
...this.state,
showCalendar: !this.state.showCalendar
})
}
render()
{
const css = this.props.classes;
const offer = this.props.offer;
const Body = () =>
<StackPanel className={css.root} centerHorizontally centerVertically orientation="vertical">
<StackPanel className={css.container} orientation="horizontal">
<StackPanel className={css.left} orientation="vertical">
<Typography className={css.typeText} variant="h6" gutterBottom>{this.state.appState.bookingTypeName} Dockage</Typography>
<Typography variant="h6" gutterBottom>
<span className={css.priceText}>$100.00</span><span className={css.priceTextExcluding}> per night excluding texes and add-ons</span>
</Typography>
<Typography className={css.offText} variant="h6">50% of (was $200)</Typography>
<StackPanel centerHorizontally centerVertically orientation="vertical" className={css.buttonContainer}>
<StackPanel {...dockTop} centerHorizontally centerVertically className={css.button} >Arrivals on 04/19/19 have a 3 night minimum stay</StackPanel>
<StackPanel {...dockBottom} centerHorizontally centerVertically className={css.button}>Space is aviable but the requestet shore power is not awiable</StackPanel>
</StackPanel>
<Typography onClick={event => this.showCalnedarHandler(event)} className={css.showCalendarText} variant="subtitle1">
Show pricing calendar
<KeyboardArrowDown className={css.selectionArrow}/>
</Typography>
</StackPanel>
<StackPanel className={css.right} orientation="vertical" centerHorizontally>
<StackPanel {...dockTop} centerHorizontally centerVertically className={css.whiteButton}>
<InformationButton text="Only 2 spaces left"/>
</StackPanel>
<StackPanel {...dockBottom} centerHorizontally centerVertically className={css.selectedButton}>
<SelectedButton text="Selected" />
</StackPanel>
</StackPanel>
</StackPanel>
{
this.state.showCalendar &&
<StackPanel className={css.calendarPanelContainer} {...dockBottom}>
<CalendarPanel searchParameters={this.state.appState.searchParameters}/>
</StackPanel>
}
</StackPanel>
return Body();
}
}
Calendar component
class CalendaPranel extends React.Component<IProps & WithStyles<typeof styles>, IState>
{
render()
{
const css = this.props.classes;
const Body = () =>
<StackPanel className={css.root} centerVertically orientation="vertical">
<StackPanel className={css.calendarContainer} centerHorizontally centerVertically>
<Calendar searchParameters={this.props.searchParameters}/>
</StackPanel>
<StackPanel className={css.legend} centerVertically orientation="horizontal">
<span className={css.unavailable}></span>Unavailable
<span className={css.available}></span>Available
<span className={css.selectedStartDay}></span>Selected Start Day
<span className={css.dateRange}></span>Date Range
</StackPanel>
<Typography className={css.legendText} variant="subtitle1">Above is the price for each night of dockage excluding taxes and add-ons</Typography>
</StackPanel>
return Body();
}
}
thnx

Mix HTML and {this.props.foo}

var User = React.createClass({
render: function() {
console.log("User");
console.log(this.props);
return (
<div className="user">
<h2 className="userName">
{this.props.name}
</h2>
<img src={this.props.avatarHash} alt="" width="100" height="100" />
</div>
);
}
});
How can I append/mix HTML with properties?
What I've tried and failed:
<img src="http://foo.bar/{this.props.avatarHash}" alt="" width="100" height="100" />
<img src="http://foo.bar/"{this.props.avatarHash} alt="" width="100" height="100" />
You can use Template literals
<img
src={ `http://foo.bar/${ this.props.avatarHash }` }
alt=""
width="100"
height="100"
/>
or String concatenation
<img
src={ 'http://foo.bar/' + this.props.avatarHash }
alt=""
width="100"
height="100"
/>

WPF key gesture PageDown shows up as Next in Menu Item

I've setup a custom command with PageDown as the key gesture, but for the MenuItem that is bound to that command the gesture shows up as "Next". The problem is that I have commands that use PageUp, Home, and End for related tasks and they all show up as expected for their MenuItems. Is there some way to make the MenuItem show "PageDown" instead of "Next" for consistency?
Here's the xaml that defines the commands.
<Window.Resources>
<RoutedUICommand x:Key="FirstPageCommand"
Text="FirstPage">
<RoutedUICommand.InputGestures>
<KeyGesture>Home</KeyGesture>
</RoutedUICommand.InputGestures>
</RoutedUICommand>
<RoutedUICommand x:Key="LastPageCommand"
Text="LastPage">
<RoutedUICommand.InputGestures>
<KeyGesture>End</KeyGesture>
</RoutedUICommand.InputGestures>
</RoutedUICommand>
<RoutedUICommand x:Key="PreviousPageCommand"
Text="PreviousPage">
<RoutedUICommand.InputGestures>
<KeyGesture>PageUp</KeyGesture>
</RoutedUICommand.InputGestures>
</RoutedUICommand>
<RoutedUICommand x:Key="NextPageCommand"
Text="NextPage">
<RoutedUICommand.InputGestures>
<KeyGesture>PageDown</KeyGesture>
</RoutedUICommand.InputGestures>
</RoutedUICommand>
</Window.Resources>
And here is where I use them in a Menu
<MenuItem Header="_View">
<MenuItem Header="_First Page"
Command="{StaticResource FirstPageCommand}">
<MenuItem.Icon>
<Image Source="Images\Backward_01.png"
Stretch="Uniform"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="_Previous Page"
Command="{StaticResource PreviousPageCommand}">
<MenuItem.Icon>
<Image Source="Images\Backward.png"
Stretch="Uniform"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="_Next Page"
Command="{StaticResource NextPageCommand}">
<MenuItem.Icon>
<Image Source="Images\Forward.png"
Stretch="Uniform"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="_Last Page"
Command="{StaticResource LastPageCommand}">
<MenuItem.Icon>
<Image Source="Images\Forward_01.png"
Stretch="Uniform"/>
</MenuItem.Icon>
</MenuItem>
</MenuItem>
My menu looks like this
View
First Page Home
Last Page PageUp
Next Page Next
Last Page End
Apparently this is only possible if you define your commands in code like this.
public class MyCommands
{
public static RoutedUICommand NextPage { get; private set; }
public static RoutedUICommand PreviousPage { get; private set; }
static OCRopingCommands()
{
NextPage = new RoutedUICommand("NextPage", "NextPage", typeof(MyCommands));
NextPage.InputGestures.Add(
new KeyGesture(Key.PageDown, ModifierKeys.None, "PageDn"));
PreviousPage = new RoutedUICommand("PreviousPage", "PreviousPage", typeof(MyCommands));
PreviousPage.InputGestures.Add(
new KeyGesture(Key.PageUp, ModifierKeys.None, "PageUp"));
}
}
And here's how you'd wire them up
<MenuItem Header="_Previous Page"
Command="local:MyCommands.PreviousPage">
<MenuItem.Icon>
<Image Source="Images\Backward.png"
Stretch="Uniform"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="_Next Page"
Command="local:MyCommands.NextPage">
<MenuItem.Icon>
<Image Source="Images\Forward.png"
Stretch="Uniform"/>
</MenuItem.Icon>
</MenuItem>
Why the KeyGesture doesn't allow you to set the display name in xaml is beyond me.

Resources