I have a project that requires a dialog to be resizable and draggable. Material-UI Dialog documentation has steps on how to make it draggable. I want to find out the resizable part. Any suggestions on how to?
Sample code can be found here.
UPDATE:
Functional and typescript version of #Khabir's answer below
import Button from '#material-ui/core/Button'
import Dialog from '#material-ui/core/Dialog'
import DialogActions from '#material-ui/core/DialogActions'
import DialogContent from '#material-ui/core/DialogContent'
import DialogContentText from '#material-ui/core/DialogContentText'
import DialogTitle from '#material-ui/core/DialogTitle'
import Paper, { PaperProps } from '#material-ui/core/Paper'
import { makeStyles, Theme } from '#material-ui/core/styles'
import TextField from '#material-ui/core/TextField'
import React from 'react'
import Draggable from 'react-draggable'
import { ResizableBox } from 'react-resizable'
const useStyles = makeStyles((theme: Theme) => ({
resizable: {
position: 'relative',
'& .react-resizable-handle': {
position: 'absolute',
width: 20,
height: 20,
bottom: 0,
right: 0,
background:"url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2IDYiIHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOiNmZmZmZmYwMCIgeD0iMHB4IiB5PSIwcHgiIHdpZHRoPSI2cHgiIGhlaWdodD0iNnB4Ij48ZyBvcGFjaXR5PSIwLjMwMiI+PHBhdGggZD0iTSA2IDYgTCAwIDYgTCAwIDQuMiBMIDQgNC4yIEwgNC4yIDQuMiBMIDQuMiAwIEwgNiAwIEwgNiA2IEwgNiA2IFoiIGZpbGw9IiMwMDAwMDAiLz48L2c+PC9zdmc+')",
'background-position': 'bottom right',
padding: '0 3px 3px 0',
'background-repeat': 'no-repeat',
'background-origin': 'content-box',
'box-sizing': 'border-box',
cursor: 'se-resize',
},
},
}))
const PaperComponent = (props: PaperProps) => {
return (
<Draggable
handle="#draggable-dialog-title"
cancel={'[class*="MuiDialogContent-root"]'}
>
<Paper {...props} />
</Draggable>
)
}
export const DialogComponent = () => {
const [open, setOpen] = React.useState<boolean>(false)
const handleClickOpen = () => {
setOpen(true)
}
const handleClose = () => {
setOpen(false)
}
const classes = useStyles()
return (
<div>
<Button onClick={handleClickOpen}>Open dd form dialog</Button>
{open && (
<Dialog
open={true}
onClose={handleClose}
maxWidth={false}
PaperComponent={PaperComponent}
aria-labelledby="draggable-dialog-title"
>
<ResizableBox
height={400}
width={600}
className={classes.resizable}
>
<DialogTitle
style={{ cursor: 'move' }}
id="draggable-dialog-title"
>
Subscribe
</DialogTitle>
<DialogContent>
<DialogContentText>
To subscribe to this website, please enter your email address here. We will send updates occasionally.
</DialogContentText>
<TextField
autoFocus
margin="dense"
id="name"
label="Email Address"
type="email"
fullWidth
/>
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="primary">
Cancel
</Button>
<Button onClick={handleClose} color="primary">
Subscribe
</Button>
</DialogActions>
</ResizableBox>
</Dialog>
)}
</div>
)
}
typescript 3.8.3
#material-ui/core 4.9.7
Hi I merged two features together. please check the example. It supports both drag and resize.
import React from "react";
import Button from "#material-ui/core/Button";
import Draggable from "react-draggable";
import {withStyles} from "#material-ui/core/styles";
import TextField from "#material-ui/core/TextField";
import Dialog from "#material-ui/core/Dialog";
import DialogActions from "#material-ui/core/DialogActions";
import DialogContent from "#material-ui/core/DialogContent";
import DialogContentText from "#material-ui/core/DialogContentText";
import DialogTitle from "#material-ui/core/DialogTitle";
import {ResizableBox} from "react-resizable";
import Paper from "#material-ui/core/Paper";
const styles = theme => ({
resizable: {
position: "relative",
"& .react-resizable-handle": {
position: "absolute",
width: 20,
height: 20,
bottom: 0,
right: 0,
background:
"url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2IDYiIHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOiNmZmZmZmYwMCIgeD0iMHB4IiB5PSIwcHgiIHdpZHRoPSI2cHgiIGhlaWdodD0iNnB4Ij48ZyBvcGFjaXR5PSIwLjMwMiI+PHBhdGggZD0iTSA2IDYgTCAwIDYgTCAwIDQuMiBMIDQgNC4yIEwgNC4yIDQuMiBMIDQuMiAwIEwgNiAwIEwgNiA2IEwgNiA2IFoiIGZpbGw9IiMwMDAwMDAiLz48L2c+PC9zdmc+')",
"background-position": "bottom right",
padding: "0 3px 3px 0",
"background-repeat": "no-repeat",
"background-origin": "content-box",
"box-sizing": "border-box",
cursor: "se-resize"
}
}
});
function PaperComponent(props) {
return (
<Draggable handle="#draggable-dialog-title" cancel={'[class*="MuiDialogContent-root"]'}>
<Paper {...props} />
</Draggable>
);
}
class DraggableResizableDialog extends React.Component {
state = {
open: false
};
handleClickOpen = () => {
this.setState({open: true});
};
handleClose = () => {
this.setState({open: false});
};
render() {
return (
<div>
<Button onClick={this.handleClickOpen}>Open dd form dialog</Button>
{this.state.open && (
<Dialog
open={true}
onClose={this.handleClose}
maxWidth={false}
PaperComponent={PaperComponent}
aria-labelledby="draggable-dialog-title"
>
<ResizableBox
height={400}
width={600}
className={this.props.classes.resizable}
>
<DialogTitle style={{ cursor: 'move' }} id="draggable-dialog-title">Subscribe</DialogTitle>
<DialogContent>
<DialogContentText>
To subscribe to this website, please enter your email address
here. We will send updates occasionally.
</DialogContentText>
<TextField
autoFocus
margin="dense"
id="name"
label="Email Address"
type="email"
fullWidth
/>
</DialogContent>
<DialogActions>
<Button onClick={this.handleClose} color="primary">
Cancel
</Button>
<Button onClick={this.handleClose} color="primary">
Subscribe
</Button>
</DialogActions>
</ResizableBox>
</Dialog>
)}
</div>
);
}
}
export default withStyles(styles)(DraggableResizableDialog);
Source: Draggable Resizable
Related
I'm trying to create a dialog pop up for my react js app, when user clicks on button, dialog opens up. I have form with input fields in that dialog, after user fills out all inputs he can submit info by clicking "submit" button at the bottom of the dialog pop up. The problem is that I don't know how to stick submit button to the footer so even if there are 15+ inputs, user doesn't have to scroll all the way down to see "submit" button. I know that material ui has DialogActions for this purpose, but because dialog is in parent component, I don't have access to DialogActions from child. My code:
App.js (parent)
import React, { useState } from "react";
import Info from "./Info";
import Dialog from "#material-ui/core/Dialog";
import { DialogTitle } from "#material-ui/core";
import DialogContent from "#material-ui/core/DialogContent";
import DialogContentText from "#material-ui/core/DialogContentText";
import { DialogActions } from "#material-ui/core";
export default function App() {
const [open, setOpen] = useState(false);
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<button onClick={handleClickOpen}>Click me to open dialog</button>
<Dialog
open={open}
aria-labelledby="responsive-dialog-title"
maxWidth="md"
setMaxWidth="md"
fullWidth={true}
>
<dialogContent>
<dialogTitle>
{" "}
<div>
<h4>Fill out the form</h4>
</div>
</dialogTitle>
<DialogContentText>
<Info />
</DialogContentText>
</dialogContent>
{/* <DialogActions>
<button id="responsive-dialog-title" onClick={handleClose}>
{" "}
Submit{" "}
</button>
</DialogActions> */}
</Dialog>{" "}
</div>
);
}
and Info.js (child) :
import React, { useState } from "react";
export default function Info() {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const handleClickOpen = () => {
setOpen(true);
};
const handleSubmit = () => {
console.log(username);
console.log(password);
console.log(address);
};
return (
<form onSubmit={handleSubmit}>
<div
style={{
display: "flex",
flexDirection: "column",
width: "350px",
padding: "20px"
}}
>
<label> Username</label>
<input
value={username}
onChange={(e) => setUsername(e.target.value)}
type="text"
/>
</div>
<div
style={{
display: "flex",
flexDirection: "column",
width: "350px",
padding: "20px"
}}
>
<label> Password</label>
<input
value={password}
onChange={(e) => setPassword(e.target.value)}
type="password"
/>
</div>
<button> Submit</button>
</form>
);
}
codesandbox
Is there any way to make that "submit" button in Info.js displayed as DialogActions/ fixed to bottom? Any help and suggestion are greatly aprreciated.
Use the position: fixed property to achieve that. Your code would look like this:
<form onSubmit={handleSubmit}>
<div>
<div
style={{
display: "flex",
flexDirection: "column",
width: "350px",
padding: "20px"
}}
>
<label> Username</label>
<input
value={username}
onChange={(e) => setUsername(e.target.value)}
type="text"
/>
</div>
<div
style={{
display: "flex",
flexDirection: "column",
width: "350px",
padding: "20px"
}}
>
<label> Password</label>
<input
value={password}
onChange={(e) => setPassword(e.target.value)}
type="password"
/>
</div>
</div>
<div style={{ position: "fixed" }}>
<button> Submit</button>
<button> Cancel</button>
</div>
</form>
The scroll that the dialog has by default also had to be removed
<Dialog
open={open}
aria-labelledby="responsive-dialog-title"
maxWidth="md"
setMaxWidth="md"
fullWidth={true}
>
<div style={{ overflow: "hidden", height: "100%", width: "100%" }}>
<dialogTitle>
{" "}
<div>
<h4>Fill out the form</h4>
</div>
</dialogTitle>
<Info />
</div>
</Dialog>
This works, but the best thing to do is call the submit function from the parent, or the submit function exists in the parent and the inputs can be filled with context or a simple state
To piggyback on a previous question, I'd like my menu to close whenever I click somewhere else other than the menu.
Currently, it will open/close when I click the "Hamburger Menu Button". It will close if I click a link on the menu or the menu itself but I'd also like to close when I "blur" away from it. This would be like if you got an alert message and you clicked somewhere else, the alert would close.
Here is the current CodeSandbox
The relevant code is in Header.tsx:
import React, { useState } from "react";
import { Link } from "react-router-dom";
import {
AppBar,
Container,
createStyles,
IconButton,
makeStyles,
Theme,
Toolbar,
Typography
} from "#material-ui/core";
import MenuIcon from "#material-ui/icons/Menu";
import clsx from "clsx";
const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
flexGrow: 1,
"& a": {
color: "white",
textDecoration: "none"
}
},
menuButton: {
marginRight: theme.spacing(2),
zIndex: 2
},
title: {
flexGrow: 1,
zIndex: 2
},
toolBar: {
"& div": {
transition: "left .1s"
}
},
menu: {
zIndex: 1,
width: 200,
height: "100%",
position: "fixed",
top: 48,
transition: "left .1s",
marginRight: theme.spacing(2),
left: -200,
background: "#3f51b5",
"& div:first-element": {
marginTop: 100
}
},
menuOpen: {
left: 0,
transition: "left .1s"
},
menuClose: {
left: -200,
transition: "left .1s"
},
topMenu: {
display: "flex",
"& div": {
marginLeft: theme.spacing(1)
}
}
})
);
const UserMenu = () => {
const classes = useStyles();
const [menuOpen, setMenuOpen] = useState(false);
const toggleMenu = () => setMenuOpen(!menuOpen);
const handleMenuClick = () => toggleMenu();
return (
<>
<IconButton
edge="start"
className={classes.menuButton}
color="inherit"
aria-label="menu"
onClick={toggleMenu}
>
<MenuIcon />
</IconButton>
<div className={classes.toolBar}>
<Container
className={clsx(classes.menu, {
[classes.menuOpen]: menuOpen,
[classes.menuClose]: !menuOpen,
[classes.toolBar]: true
})}
onClick={handleMenuClick}
>
<div>
<Link to="#">My Profile</Link>
</div>
<div>
<Link to="#">Account</Link>
</div>
<div>
<Link to="#">Admin</Link>
</div>
</Container>
</div>
</>
);
};
const Header: React.FC = ({ children }) => {
const classes = useStyles();
return (
<AppBar position="static" className={classes.root}>
<Toolbar variant="dense">
<UserMenu />
<Typography variant="h6" className={classes.title}>
<Link to="#">Widgets, LLC</Link>
</Typography>
<div className={classes.topMenu}>
<div>
<Link to="#">Sign out</Link>
</div>
<div>
<Link to="#">One more</Link>
</div>
</div>
</Toolbar>
</AppBar>
);
};
export default Header;
**Edit: ** This is the current Sandbox after applying Ryan's changes and moving the UserMenu into its own file.
You can use Material-UI's ClickAwayListener for this. The only tricky part is avoiding an immediate close of your menu after clicking on the button to open the menu (because of the click event being handled by the button opening the menu and then the same click event being handled by the ClickAwayListener closing the menu). Typically you would want to avoid rendering the ClickAwayListener until the menu is open, but I think that might break the transition on the menu unless you did further changes. My example addresses this problem by calling event.stopPropagation() in the click handler for the menu button (handleOpen).
Here's a modified version of your code/sandbox demonstrating this:
import React, { useState } from "react";
import { Link } from "react-router-dom";
import {
AppBar,
Container,
ClickAwayListener,
createStyles,
IconButton,
makeStyles,
Theme,
Toolbar,
Typography
} from "#material-ui/core";
import MenuIcon from "#material-ui/icons/Menu";
import clsx from "clsx";
const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
flexGrow: 1,
"& a": {
color: "white",
textDecoration: "none"
}
},
menuButton: {
marginRight: theme.spacing(2),
zIndex: 2
},
title: {
flexGrow: 1,
zIndex: 2
},
toolBar: {
"& div": {
transition: "left .1s"
}
},
menu: {
zIndex: 1,
width: 200,
height: "100%",
position: "fixed",
top: 48,
transition: "left .1s",
marginRight: theme.spacing(2),
left: -200,
background: "#3f51b5",
"& div:first-element": {
marginTop: 100
}
},
menuOpen: {
left: 0,
transition: "left .1s"
},
menuClose: {
left: -200,
transition: "left .1s"
},
topMenu: {
display: "flex",
"& div": {
marginLeft: theme.spacing(1)
}
}
})
);
const UserMenu = () => {
const classes = useStyles();
const [menuOpen, setMenuOpen] = useState(false);
const handleOpen = (event: React.MouseEvent) => {
if (!menuOpen) {
event.stopPropagation();
setMenuOpen(true);
}
};
const handleClose = (event: React.MouseEvent<any, MouseEvent>) => {
if (menuOpen) {
setMenuOpen(false);
}
};
return (
<>
<IconButton
edge="start"
className={classes.menuButton}
color="inherit"
aria-label="menu"
onClick={handleOpen}
>
<MenuIcon />
</IconButton>
<div className={classes.toolBar}>
<ClickAwayListener onClickAway={handleClose}>
<Container
className={clsx(classes.menu, {
[classes.menuOpen]: menuOpen,
[classes.menuClose]: !menuOpen,
[classes.toolBar]: true
})}
onClick={handleClose}
>
<div>
<Link to="#">My Profile</Link>
</div>
<div>
<Link to="#">Account</Link>
</div>
<div>
<Link to="#">Admin</Link>
</div>
</Container>
</ClickAwayListener>
</div>
</>
);
};
const Header: React.FC = ({ children }) => {
const classes = useStyles();
return (
<AppBar position="static" className={classes.root}>
<Toolbar variant="dense">
<UserMenu />
<Typography variant="h6" className={classes.title}>
<Link to="#">Widgets, LLC</Link>
</Typography>
<div className={classes.topMenu}>
<div>
<Link to="#">Sign out</Link>
</div>
<div>
<Link to="#">One more</Link>
</div>
</div>
</Toolbar>
</AppBar>
);
};
export default Header;
This is Header.js where I have the button <ReactSvg>, inside <IconButton> when you click it, it will change the page theme with the switchTheme() function. When you hover over the button it also has a popover where it declares the function of the button (ex. switch theme).
For some reason I hover the button the popover comes out but doesn't let me click on the button even if I click very fast and vigorously. Somehow the popover has disabled the button.
Header file where the button is rendered:
import React, { useState } from 'react'
import ReactSvg from './reactSvg'
import { Box, Typography, Link, Container, IconButton } from '#material-ui/core'
import PhoneIcon from '#material-ui/icons/Phone'
import EmailIcon from '#material-ui/icons/Email'
import GitHubIcon from '#material-ui/icons/GitHub'
import LinkedInIcon from '#material-ui/icons/LinkedIn'
import { useStyles } from '../styles/customStyles'
import Image from 'material-ui-image'
import PopOver from './PopOver'
const styles = {
image: {
maxWidth: 200,
minWidth: 200,
},
}
export default function Header({ switchTheme }) {
const classes = useStyles()
const [anchorEl, setAnchorEl] = useState(null)
const handleTheme = () => {
switchTheme()
}
const handleHover = (e) => {
setAnchorEl(e.currentTarget)
}
return (
<>
<Box>
<IconButton onClick={() => handleTheme()} onMouseOver={(e) => handleHover(e)}>
<ReactSvg />
</IconButton>
<Typography variant="h3" color="primary">
Staz Christodoulakis
</Typography>
<Typography variant="body1" color="primary">
Software Engineer ยท Web/App
</Typography>
<hr className="solid" />
<Box
display="flex"
alignItems="center"
justifyContent="center"
className={classes.root}
flexWrap="wrap"
>
<Link color="secondary" variant="body1" href="tel: 650-409-6202">
<Box display="flex">
<PhoneIcon /> 650 409 6202
</Box>
</Link>
<Link color="secondary" variant="body1" href="mailto: staz.christo#gmail.com">
<Box display="flex">
<EmailIcon /> staz.christo#gmail.com
</Box>
</Link>
<Link href="https://github.com/stazcp" color="secondary" variant="body1">
<Box display="flex">
<GitHubIcon /> github.com/stazcp
</Box>
</Link>
<Link href="https://www.linkedin.com/in/staz-christo" color="secondary" variant="body1">
<Box display="flex">
<LinkedInIcon /> linkedin.com/in/staz-christo
</Box>
</Link>
</Box>
</Box>
<PopOver anchorEl={anchorEl} setAnchorEl={setAnchorEl} />
</>
)
}
Popover:
import React, { useState, useEffect } from 'react'
import { makeStyles } from '#material-ui/core/styles'
import Popover from '#material-ui/core/Popover'
import Typography from '#material-ui/core/Typography'
import Button from '#material-ui/core/Button'
const useStyles = makeStyles((theme) => ({
typography: {
padding: theme.spacing(2),
},
}))
export default function SimplePopover({ anchorEl, setAnchorEl }) {
const classes = useStyles()
const handleClose = () => {
setAnchorEl(null)
}
const open = Boolean(anchorEl)
const id = open ? 'simple-popover' : undefined
return (
<div>
<Popover
id={id}
open={open}
anchorEl={anchorEl}
onClose={handleClose}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'center',
}}
transformOrigin={{
vertical: 'top',
horizontal: 'center',
}}
>
<Typography className={classes.typography}>
Click on React Symbol to change theme!
</Typography>
</Popover>
</div>
)
}
Why is that the onMouseOver event blocking the onClick event?
Can you try stopPropagation?
const handleHover = (e) => {
e.stopPropagation();
setAnchorEl(e.currentTarget)
}
So I found a solution to my problem by using a Tooltip provided by Material UI.
https://material-ui.com/components/tooltips/
Like this:
<Tooltip title="Click Me!" placement="right" arrow>
<IconButton
onClick={() => handleTheme()}
// onMouseOver={(e) => handleHover(e)}
>
<GetIcon icon={reactLogo} className="reactLogo" />
</IconButton>
</Tooltip>
if anyone has managed to use different methods for mouse events on Material UI buttons please post here.
Thanks!
If I click to remove the first like on the first goal, I can see the Redux action firing (using Redux DevTools) for the like being updated. But the number beside is not updating. When I check the console it doesn't appear that anything is refreshing. When I refresh the page, it shows the updated number that was previously liked (the 0 becomes a 1), but I have to refresh the page to see this update. How can I get the number to update in real time without having to refresh the page?
import React, { useEffect } from "react";
import Moment from "react-moment";
import PropTypes from "prop-types";
import { Link } from "react-router-dom";
import { connect } from "react-redux";
import { addLike, removeLike } from "../../actions/goal";
import { getGoals } from "../../actions/goal";
import Spinner from "../layout/Spinner";
import Navbar from "../dashboard/Navbar";
import ThumbUpAltIcon from "#material-ui/icons/ThumbUpAlt";
import ThumbDownAltIcon from "#material-ui/icons/ThumbDownAlt";
import ChatIcon from "#material-ui/icons/Chat";
import DeleteIcon from "#material-ui/icons/Delete";
import DoneIcon from "#material-ui/icons/Done";
import {
Typography,
Container,
CssBaseline,
makeStyles,
Grid,
Avatar,
Paper,
Button
} from "#material-ui/core";
const useStyles = makeStyles(theme => ({
paper: {
height: "auto",
marginBottom: theme.spacing(3)
},
actionButtons: {
marginTop: "3vh"
},
profileHeader: {
textAlign: "center",
marginBottom: 20
},
avatar: {
width: theme.spacing(7),
height: theme.spacing(7)
}
}));
const Goals = ({
getGoals,
auth,
addLike,
removeLike,
goal: { goals, user, loading }
}) => {
useEffect(() => {
getGoals();
}, [getGoals]);
const classes = useStyles();
return loading ? (
<>
<Navbar />
<Container component="main" maxWidth="xs">
<CssBaseline />
<div className={classes.paper}>
<Spinner />
</div>
</Container>
</>
) : (
<>
<CssBaseline />
<Navbar />
<main>
<Container>
<Typography variant="h2" className={classes.profileHeader}>
Goals
</Typography>
{/* parent grid */}
<Grid container spacing={4}>
{goals.map(singleGoal => (
<Grid
className={classes.paper}
key={singleGoal._id}
spacing={1}
container
item
direction="row"
alignItems="center"
component={Paper}
>
<Grid
item
container
direction="column"
justify="center"
alignItems="center"
xs={3}
>
<Avatar className={classes.avatar} src={singleGoal.avatar} />
<Typography variant="caption">
{singleGoal.first_name} {singleGoal.last_name}
</Typography>
<Typography variant="caption" className={classes.postedOn}>
Posted on{" "}
<Moment format="MM/DD/YYYY">{singleGoal.date}</Moment>
</Typography>
</Grid>
<Grid container item direction="column" xs={9}>
<Typography variant="body1">{singleGoal.text}</Typography>
<Grid item className={classes.actionButtons}>
<Button size="small" onClick={e => addLike(singleGoal._id)}>
<ThumbUpAltIcon />
</Button>
<Typography variant="caption">
{singleGoal.likes.length}
</Typography>
<Button
size="small"
onClick={e => removeLike(singleGoal._id)}
>
<ThumbDownAltIcon />
</Button>
<Button href={`/goal/${singleGoal._id}`} size="small">
<ChatIcon />
</Button>
{!auth.loading && singleGoal.user === auth.user._id && (
<Button size="small">
<DoneIcon />
</Button>
)}
{!auth.loading && singleGoal.user === auth.user._id && (
<Button size="small">
<DeleteIcon />
</Button>
)}
</Grid>
</Grid>
</Grid>
))}
</Grid>
</Container>
</main>
</>
);
};
Goals.propTypes = {
getGoals: PropTypes.func.isRequired,
goal: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
goal: state.goal,
auth: state.auth
});
export default connect(mapStateToProps, { getGoals, addLike, removeLike })(
Goals
);
I will need to see the rest of your code to be sure, but it seems you are dispatching your action but you are not updating your store, it could be a mistake in your reducer.
I have an AppBar component and I want to combine it with a drawer, this is the AppBar code:
import React from "react";
import PropTypes from "prop-types";
import { withStyles } from "material-ui/styles";
import AppBar from "material-ui/AppBar";
import Toolbar from "material-ui/Toolbar";
import Typography from "material-ui/Typography";
import Button from "material-ui/Button";
import IconButton from "material-ui/IconButton";
import MenuIcon from "material-ui-icons/Menu";
import TemporaryDrawer from "./Drawer";
const styles = {
root: {
width: "100%"
},
flex: {
flex: 1
},
menuButton: {
marginLeft: -12,
marginRight: 20
},
};
function ButtonAppBar(props) {
const { classes } = props;
return (
<div className={classes.root}>
<TemporaryDrawer/>
<AppBar position="static">
<Toolbar>
<IconButton className={classes.menuButton} color="inherit" aria-label="Menu">
<MenuIcon />
</IconButton>
<Typography variant="title" color="inherit" className={classes.flex}>
Title
</Typography>
<Button color="inherit">Drawer</Button>
</Toolbar>
</AppBar>
</div>
);
}
ButtonAppBar.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(ButtonAppBar);
Currently I'm using material-ui v1.0.0-beta.33, what I want is to open a drawer on the left side when click on the Button I have in AppBar but I have no idea how to do this.
I'll appreciate the help on this.
If I understand you correctly you can do it this way - store the boolean value that indicates is the drawer is opened in the state of your component:
state = { drawerIsOpen: false }
You will change it when user clicks on your Button:
handleDrawerOpen = () => {
this.setState({ drawerIsOpen: true });
};
Your render method should look like this:
render() {
const { classes } = this.props;
return (
<div className={classes.root}>
<AppBar position="static">
<Toolbar>
<IconButton className={classes.menuButton} color="inherit" aria-label="Menu">
<MenuIcon />
</IconButton>
<Typography variant="title" color="inherit" className={classes.flex}>
Title
</Typography>
<Button onClick={this.handleDrawerOpen} color="inherit">Drawer</Button>
</Toolbar>
</AppBar>
<Drawer
variant="persistent"
classes={{
paper: classes.drawerPaper,
}}
open={this.state.drawerIsOpen}
>
<div className={classes.drawerHeader}>
<IconButton onClick={this.handleDrawerClose}>
<ChevronLeftIcon />
</IconButton>
</div>
<div className={classes.drawerInner}>
<p>drawer content</p>
</div>
</Drawer>
</div>
);
}
Check this simplified demo (see demo.js file).