I followed the material UI snack bar for a simple snackbar example. But instead of having a separate button to display snackbar message I want the message to appear when my existing button is clicked.
SnackBarTest.tsx --> ref Reference Link
import React from 'react';
import Button from '#material-ui/core/Button';
import Snackbar from '#material-ui/core/Snackbar';
import IconButton from '#material-ui/core/IconButton';
import CloseIcon from '#material-ui/icons/Close';
export default function SnackBarTest() {
const [open, setOpen] = React.useState(false);
const handleClick = () => {
setOpen(true);
};
const handleClose = (event: React.SyntheticEvent | React.MouseEvent, reason?: string) => {
if (reason === 'clickaway') {
return;
}
setOpen(false);
};
return (
<div>
<Button onClick={handleClick}>Open simple snackbar</Button>
<Snackbar
anchorOrigin={{
vertical: 'bottom',
horizontal: 'left',
}}
open={open}
autoHideDuration={6000}
onClose={handleClose}
message="Note archived"
action={
<React.Fragment>
<Button color="secondary" size="small" onClick={handleClose}>
UNDO
</Button>
<IconButton size="small" aria-label="close" color="inherit" onClick={handleClose}>
<CloseIcon fontSize="small" />
</IconButton>
</React.Fragment>
}
/>
</div>
);
}
Now inside my sample.tsx file
import SnackBarTest from './SnackBarTest';
class Sample extends React.Component {
submitButton(){
//doing some work
}
render(){
return(
<div>
<Button onClick={this.submitButton}>Submit<Button/>
<SnackBarTest />
</div>
)
}
Inside my sample.tsx It will show my existing button and second button for the snack bar. How am I able to move the SnackBarTest button functionality into my existing Button?
Related
I am new here and I saw some related answer but it will use another package and class components, i have functional component and use MUI Dialog for popup but the functionality is only for one modal but I have many modal my code
import React from 'react'
import Image from '../../assets/images/banner1.png'
import Dialog from '#mui/material/Dialog';
import DialogActions from '#mui/material/DialogActions';
import DialogContent from '#mui/material/DialogContent';
import DialogContentText from '#mui/material/DialogContentText';
import DialogTitle from '#mui/material/DialogTitle';
import Button from '#mui/material/Button';
export default function Popups() {
const [open, setOpen] = React.useState(false);
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div className='image-data-grids'>
<div className='image-and-data-section'>
<img onClick={handleClickOpen} className='image-data-grid-image' src={Image} alt='Img' />
</div>
<Dialog
open={open}
onClose={handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogContent>
<DialogContentText id="alert-dialog-description">
Content1
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Disagree</Button>
</DialogActions>
</Dialog>
<div className='image-and-data-section'>
<img onClick={handleClickOpen} className='image-data-grid-image' src={Image} alt='Img' />
</div>
<Dialog
open={open}
onClose={handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogContent>
<DialogContentText id="alert-dialog-description">
content2
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Disagree</Button>
</DialogActions>
</Dialog>
</div>
)
}
here handleClickOpen and handleClose are the function for open and close for single modal, i have multiple modals. how customize these two function for multiple modal, i am new in react please help me to solve this issue, Thanks in advance
I know you are talking about having multiple state dependencies within a Component. I think you can do this
function StackOverflow() {
// We create a state dep that holds all our modals open/close state
const [myModals, setMyModals] = useState({
modalA: true,
modalB: false,
})
// This will return an api in which we can toggle, close or open a modal
// ie: set the boolean to true or false
const getModalHanlder = (modalName) => {
return {
isOpen: myModals[modalName],
open: () => setMyModals((state) => ({ ...state, [modalName]: true })),
close: () => setMyModals((state) => ({ ...state, [modalName]: false })),
toggle: () =>
setMyModals((state) => ({ ...state, modalA: !state[modalName] })),
}
}
const modalA = getModalHanlder("modalA")
// Here we invoke our function and pass on the desired modal prop name from
// which we desire to create an api
// We can then create this for another modal, modalB
const modalB = getModalHanlder("modalB")
return (
<div>
<b>MODAL_A: {`${modalA.isOpen}`}</b>
<br />
<button onClick={modalA.toggle}>TOGGLE</button>
<button onClick={modalA.close}>CLOSE</button>
<button onClick={modalA.open}>OPEN</button>
</div>
)
}
This is one approach another one can be to create an state for each modal, like
const [isOpenModalA, setIsOpenModalA] = useState(false)
// And this for each modal state
A fancy one can be to use a hook as useReducer and update each modal state that depends on actions you dispatch, https://reactjs.org/docs/hooks-reference.html#usereducer
I'm trying to make a reusable confirmation modal with Material UI but when I press CANCEL or OK the modal does not close.
The code is here:
https://codesandbox.io/s/lucid-hoover-sput6?file=/src/App.js
I can't figure it out why the pop don't dissapear.
LE: added the code here so it remains
ConfirmModal.js
import React from "react";
import { Button } from "#material-ui/core";
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";
const ConfirmModal = (props) => {
const { content, open, setOpen, onConfirm } = props;
return (
<Dialog
open={open}
onClose={() => setOpen(false)}
aria-labelledby="dialog-title"
>
<DialogContent>
<DialogContentText>{content}</DialogContentText>
</DialogContent>
<DialogActions>
<Button autoFocus onClick={() => setOpen(false)} color="primary">
Cancel
</Button>
<Button
onClick={() => {
setOpen(false);
onConfirm();
}}
color="primary"
>
OK
</Button>
</DialogActions>
</Dialog>
// </div>
);
};
export default ConfirmModal;
App.js
import React, { useState } from "react";
import { IconButton } from "#material-ui/core";
import { Input as InputIcon } from "#material-ui/icons";
import ConfirmModal from "./ConfirmModal";
export default function App() {
const [confirmOpen, setConfirmOpen] = useState(false);
const handleLogout = () => {
console.log("this hould logout the user");
};
return (
<div className="App">
<h2>Press the button below so the confirmation modal appears </h2>
<IconButton color="inherit" onClick={() => setConfirmOpen(true)}>
<InputIcon />
<ConfirmModal
content="Are you sure you want to leeeave us ?"
open={confirmOpen}
setOpen={setConfirmOpen}
onConfirm={handleLogout}
/>
</IconButton>
</div>
);
}
Move the modal out of the button. The Modal's cancel/confirm/backdrop click events are propagating (bubbling) up to the open button (IconButton) and its onClick handler is just reopening the modal by setting confirmOpen state true.
export default function App() {
const [confirmOpen, setConfirmOpen] = useState(false);
const handleLogout = () => {
console.log("this hould logout the user");
};
return (
<div className="App">
<h2>Press the button below so the confirmation modal appears </h2>
<IconButton color="inherit" onClick={() => setConfirmOpen(true)}>
<InputIcon />
</IconButton>
<ConfirmModal
content="Are you sure you want to leeeave us ?"
open={confirmOpen}
setOpen={setConfirmOpen}
onConfirm={handleLogout}
/>
</div>
);
}
I have been trying to create a component per function in my app, but I am facing the following issue.
I have the component DisplayAllData that sends the data and an actionable button to DisplayDataWithButton, the issue is that when someone clicks on the Button send in the props, the function modifies the state of the parent component, which is also sent as a parameter to FullScreenDialog, and that throws a Warning: Cannot update a component while rendering a different component.
I designed the components in this particular way because:
DisplayAllData is the only function that has the data to render and the actionable button. (Model)
DisplayDataWithButton only renders the data and displays the actionable components for that particular data, in this case a button that opens a Dialog in screen. (Viewer)
You can find a running example here: https://codesandbox.io/s/material-demo-forked-8oyef
import React from "react";
import Button from "#material-ui/core/Button";
import DisplayDataWithButton from "./DisplayDataWithButton";
import FullScreenDialog from "./fullscreendialog";
export default function App(props) {
const [openFullScreen, setopenFullScreen] = React.useState(false);
var items = ["John", "Melinda"];
var dataDisplayFunction = (data) => {
return data.map((item) => {
return [
item,
<Button
color="success"
size="small"
className="px-2"
variant="contained"
onClick={setopenFullScreen()}
>
Show Dialog
</Button>
];
});
};
return (
<>
<DisplayDataWithButton
shapeDataFunction={dataDisplayFunction}
data={items}
/>
<FullScreenDialog open={openFullScreen} />
</>
);
}
DisplayDataWithButton.js
export default function DisplayDataWithButton(props) {
return props.shapeDataFunction(props.data);
}
I suspect that there is another way to implement this model, any suggestion, or ideas on how to fix this one.
Thanks
A couple of things: "I have been trying to create a component per function in my app". Forget that - the pattern you have opted for here is called render props but I don't see how it is necessary. Keep it simple. If a big component is simpler to understand than a small component I always opt for the bigger component. Splitting your components will not magically make them easier to understand.
All of the warnings have been dealt with. Most of them were simple mistakes, for example: onClick={setopenFullScreen()} should be onClick={setopenFullScreen}. You can compare your sandbox with my sandbox for all of the changes.
import React from "react";
import ReactDOM from "react-dom";
import Button from "#material-ui/core/Button";
import FullScreenDialog from "./fullscreendialog";
export default function App() {
const [openFullScreen, setopenFullScreen] = React.useState(false);
const items = ["John", "Melinda"];
return (
<>
{items.map((item) => [
item,
<Button
key={item}
color="primary"
size="small"
className="px-2"
variant="contained"
onClick={() => setopenFullScreen((prev) => !prev)}
>
Show Dialog
</Button>
])}
<FullScreenDialog open={openFullScreen} />
</>
);
}
ReactDOM.render(<App />, document.querySelector("#root"));
import React from "react";
import { makeStyles } from "#material-ui/core";
import Button from "#material-ui/core/Button";
import Dialog from "#material-ui/core/Dialog";
import ListItemText from "#material-ui/core/ListItemText";
import ListItem from "#material-ui/core/ListItem";
import List from "#material-ui/core/List";
import Divider from "#material-ui/core/Divider";
import AppBar from "#material-ui/core/AppBar";
import Toolbar from "#material-ui/core/Toolbar";
import IconButton from "#material-ui/core/IconButton";
import Typography from "#material-ui/core/Typography";
import CloseIcon from "#material-ui/icons/Close";
import Slide from "#material-ui/core/Slide";
const useStyles = makeStyles((theme) => ({
appBar: {
position: "relative"
},
title: {
marginLeft: theme.spacing(2),
flex: 1
}
}));
const Transition = React.forwardRef(function Transition(props, ref) {
return <Slide direction="up" ref={ref} {...props} />;
});
export default function FullScreenDialog(props) {
const classes = useStyles();
const [open, setOpen] = React.useState(false);
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div>
<Dialog
fullScreen
open={props.open}
onClose={handleClose}
TransitionComponent={Transition}
>
<AppBar className={classes.appBar}>
<Toolbar>
<IconButton
edge="start"
color="inherit"
onClick={handleClose}
aria-label="close"
>
<CloseIcon />
</IconButton>
<Typography variant="h6" className={classes.title}>
Sound
</Typography>
<Button autoFocus color="inherit" onClick={handleClose}>
save
</Button>
</Toolbar>
</AppBar>
<List>
<ListItem button>
<ListItemText primary="Phone ringtone" secondary="Titania" />
</ListItem>
<Divider />
<ListItem button>
<ListItemText
primary="Default notification ringtone"
secondary="Tethys"
/>
</ListItem>
</List>
</Dialog>
</div>
);
}
may somebody please help me customize/disable the Material-UI Dialog's touch mechanics? I have the Cancel and Confirm buttons, and that's just what I want to use to close the dialog. However, making a selection from a dropdown menu caused the dialog to autoclose according to the doc. And I couldn't see how to do that in the doc itself.
The problem
The problem I have is that the auto-closing is doing the job I want the cancel button to do. i.e: Closing the dialog and empty an array.
I'd appreciate your help.
Any special reason to use the Material-UI Simple Dialog?
From your question, seems like a Confirmation dialog is what you're looking for :)
Simple dialog touch mechanism
Touch mechanics:
Choosing an option immediately commits the option and closes the menu
Touching outside of the dialog, or pressing Back, cancels the action and closes the dialog
In the other hand, matching your needs:
Confirmation dialogs
Confirmation dialogs require users to explicitly confirm their choice before an option is committed. For example, users can listen to multiple ringtones but only make a final selection upon touching “OK”.
Touching “Cancel” in a confirmation dialog, or pressing Back, cancels the action, discards any changes, and closes the dialog.
import React from 'react';
import PropTypes from 'prop-types';
import { makeStyles } from '#material-ui/core/styles';
import Button from '#material-ui/core/Button';
import List from '#material-ui/core/List';
import ListItem from '#material-ui/core/ListItem';
import ListItemText from '#material-ui/core/ListItemText';
import DialogTitle from '#material-ui/core/DialogTitle';
import DialogContent from '#material-ui/core/DialogContent';
import DialogActions from '#material-ui/core/DialogActions';
import Dialog from '#material-ui/core/Dialog';
import RadioGroup from '#material-ui/core/RadioGroup';
import Radio from '#material-ui/core/Radio';
import FormControlLabel from '#material-ui/core/FormControlLabel';
const options = [
'None',
'Atria',
'Callisto',
'Dione',
'Ganymede',
'Hangouts Call',
'Luna',
'Oberon',
'Phobos',
'Pyxis',
'Sedna',
'Titania',
'Triton',
'Umbriel',
];
function ConfirmationDialogRaw(props) {
const { onClose, value: valueProp, open, ...other } = props;
const [value, setValue] = React.useState(valueProp);
const radioGroupRef = React.useRef(null);
React.useEffect(() => {
if (!open) {
setValue(valueProp);
}
}, [valueProp, open]);
const handleEntering = () => {
if (radioGroupRef.current != null) {
radioGroupRef.current.focus();
}
};
const handleCancel = () => {
onClose();
};
const handleOk = () => {
onClose(value);
};
const handleChange = (event) => {
setValue(event.target.value);
};
return (
<Dialog
disableBackdropClick
disableEscapeKeyDown
maxWidth="xs"
onEntering={handleEntering}
aria-labelledby="confirmation-dialog-title"
open={open}
{...other}
>
<DialogTitle id="confirmation-dialog-title">Phone Ringtone</DialogTitle>
<DialogContent dividers>
<RadioGroup
ref={radioGroupRef}
aria-label="ringtone"
name="ringtone"
value={value}
onChange={handleChange}
>
{options.map((option) => (
<FormControlLabel value={option} key={option} control={<Radio />} label={option} />
))}
</RadioGroup>
</DialogContent>
<DialogActions>
<Button autoFocus onClick={handleCancel} color="primary">
Cancel
</Button>
<Button onClick={handleOk} color="primary">
Ok
</Button>
</DialogActions>
</Dialog>
);
}
ConfirmationDialogRaw.propTypes = {
onClose: PropTypes.func.isRequired,
open: PropTypes.bool.isRequired,
value: PropTypes.string.isRequired,
};
const useStyles = makeStyles((theme) => ({
root: {
width: '100%',
maxWidth: 360,
backgroundColor: theme.palette.background.paper,
},
paper: {
width: '80%',
maxHeight: 435,
},
}));
export default function ConfirmationDialog() {
const classes = useStyles();
const [open, setOpen] = React.useState(false);
const [value, setValue] = React.useState('Dione');
const handleClickListItem = () => {
setOpen(true);
};
const handleClose = (newValue) => {
setOpen(false);
if (newValue) {
setValue(newValue);
}
};
return (
<div className={classes.root}>
<List component="div" role="list">
<ListItem button divider disabled role="listitem">
<ListItemText primary="Interruptions" />
</ListItem>
<ListItem
button
divider
aria-haspopup="true"
aria-controls="ringtone-menu"
aria-label="phone ringtone"
onClick={handleClickListItem}
role="listitem"
>
<ListItemText primary="Phone ringtone" secondary={value} />
</ListItem>
<ListItem button divider disabled role="listitem">
<ListItemText primary="Default notification ringtone" secondary="Tethys" />
</ListItem>
<ConfirmationDialogRaw
classes={{
paper: classes.paper,
}}
id="ringtone-menu"
keepMounted
open={open}
onClose={handleClose}
value={value}
/>
</List>
</div>
);
}
you can have a look of the working dialog here:
https://4zgol.csb.app/
Hope it helps and if not, feel free to explain more about the problem or even add a code snippet :)
i want to use components(LIke: DropDown menu) in Class Component in Material Ui. i am using material-UI
and i am using class Component for.but get hooks error. i am using typescript with material UI. but i want to use Component. But I cant figure out how to do this.i am using typescript with material UI.
import React, { Component } from 'react'
import ApiService from "../../service/ApiService";
import DeleteIcon from '#material-ui/icons/Delete';
import Typography from '#material-ui/core/Typography';
import { Grid } from '#material-ui/core';
import Button from '#material-ui/core/Button';
import Menu from '#material-ui/core/Menu';
import MenuItem from '#material-ui/core/MenuItem';
class CategoryListUserComponent extends Component<any,any>{
constructor(props: any){
super(props)
this.state = {
users: [],
message: null
}
this.deleteUser = this.deleteUser.bind(this);
this.editUser = this.editUser.bind(this);
this.addUser = this.addUser.bind(this);
this.reloadUserList = this.reloadUserList.bind(this);
}
render() {
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
return (
<Grid>
<Typography variant="h4" align="left" style={style}>Category List</Typography>
<Button variant="contained" color="primary" onClick={() => this.addUser()}>
Add Category
</Button>
<Grid container className="listContainer">
<div>
<Button aria-controls="simple-menu" aria-haspopup="true" onClick={handleClick}>
Open Menu
</Button>
<Menu
id="simple-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
>
<MenuItem onClick={handleClose}>Profile</MenuItem>
<MenuItem onClick={handleClose}>My account</MenuItem>
<MenuItem onClick={handleClose}>Logout</MenuItem>
</Menu>
</div>
</Grid>
</Grid>
);
}
}
const style ={
display: 'flex',
justifyContent: 'center'
}
export default CategoryListUserComponent;