I am very new to React so this may seem a little trivial. I have a delete icon in one file which when clicked, I am trying to program a confirmation dialog box. Using the source of their website: https://material-ui.com/components/dialogs/. My file is comprises of a listview:
ListView:
import React from 'react';
import PropTypes from 'prop-types';
import { List, ListItem, ListItemText, ListItemAvatar, Avatar, ListItemSecondaryAction, IconButton } from '#material-ui/core';
import DeleteIcon from '#material-ui/icons/Delete';
import AlertDialog from './AlertDialog'
// Import CSS
import './ListViewer.css'
export function ListViewer({ objects}) {
return (
<div className='list-viewer'>
<List>
<ListItem alignItems="center" divider key={obj.id}>
<ListItemText primary={objects.name} />
<ListItemSecondaryAction>
<IconButton edge="end" aria-label="delete" onClick={handleClickOpen()}>
<DeleteIcon />
</IconButton>
</ListItemSecondaryAction>
</ListItem>
</List>
</div>
);
}
AlertDialog.js:
import React from 'react';
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';
export default function AlertDialog() {
const [open, setOpen] = React.useState(false);
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div>
{/* <Button variant="outlined" color="primary" onClick={handleClickOpen}>
Open alert dialog
</Button> */}
<Dialog
open={open}
onClose={handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">{"Are you sure you want to delete this object?"}</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-description">
Deleting this object will permanently remove it
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="primary">
Cancel
</Button>
<Button onClick={handleClose} color="primary" autoFocus>
Delete
</Button>
</DialogActions>
</Dialog>
</div>
);
}
As you can see in AlertDialog, there was initially a button which triggers the dialog to open. Instead from my other file, when the delete icon is clicked, I am trying to trigger the dialog. How can I do this? I have imported AlertDialog and AlertDialog.handleClickOpen but this does not work as handleClickOpen is not a function
You can pass open and onClose via props into AlertDialog.
function AlertDialog(props) {
const { open, onClose } = props
return (
<Dialog
open={open}
onClose={onClose}
>
{/* Dialog content */}
</Dialog>
Then, simply use it in ListView:
function ListView() {
const [dialogIsOpen, setDialogIsOpen] = React.useState(false)
const openDialog = () => setDialogIsOpen(true)
const closeDialog = () => setDialogIsOpen(false)
return (
<div className='list-viewer'>
<List>{/* Now you can set dialogIsOpen here */}</List>
<AlertDialog open={dialogIsOpen} onClose={closeDialog} />
</div>
)
}
There are a few steps how I would do it the first is that I would do instead of a open and close function I would do one as this:
const toggleDialog = useCallback(() => {
setOpen(!open);
}, [open]);
The useCallback function makes it that it only creates a new function when the parameter in the [] changes, means when open changes.
Sadly #Code-Apprentice was faster and metioned the rest to it.
<IconButton edge="end" aria-label="delete" onClick={handleClickOpen()}>
The onClick handler here must be in the same class that renders the <IconButton>. Also, remove the parentheses to set the onClick prop to the function instead of its return value:
onClick={handleClickOpen}
Related
I am using https://react-spectrum.adobe.com/react-spectrum/Dialog.html and whenever I close the dialog and reopen it the value I type does not default back to the initial state. How can I render Dialog on close to reset all states within the dialog?
import {
ActionButton,
Button,
ButtonGroup,
Content,
Dialog,
DialogTrigger,
Divider,
Header,
Heading,
Text,
TextField,
} from "#adobe/react-spectrum";
import { useState } from "react";
export const DialogBox = () => {
const [value, setValue] = useState("");
return (
<DialogTrigger>
<ActionButton>Check connectivity</ActionButton>
{(close) => (
<Dialog>
<Heading>Internet Speed Test</Heading>
<Header>Connection status: Connected</Header>
<Divider />
<Content>
<TextField value={value} onChange={setValue} />
</Content>
<ButtonGroup>
<Button variant="secondary" onPress={close}>
Cancel
</Button>
<Button variant="cta" onPress={close}>
Confirm
</Button>
</ButtonGroup>
</Dialog>
)}
</DialogTrigger>
);
};
Run setValue('') before closing
import {
ActionButton,
Button,
ButtonGroup,
Content,
Dialog,
DialogTrigger,
Divider,
Header,
Heading,
Text,
TextField,
} from "#adobe/react-spectrum";
import { useState } from "react";
export const DialogBox = () => {
const [value, setValue] = useState("");
return (
<DialogTrigger>
<ActionButton>Check connectivity</ActionButton>
{(close) => {
const onClose = () => {
setValue('')
close()
}
return (
<Dialog>
<Heading>Internet Speed Test</Heading>
<Header>Connection status: Connected</Header>
<Divider />
<Content>
<TextField value={value} onChange={setValue} />
</Content>
<ButtonGroup>
<Button variant="secondary" onPress={onClose }>
Cancel
</Button>
<Button variant="cta" onPress={onClose }>
Confirm
</Button>
</ButtonGroup>
</Dialog>
)
}
)}
</DialogTrigger>
);
};
#Konrad Linkowski 's is good,
but I would recommend a better structure.
You can read from their docs about: handling events.
In the event handling you can add the setValue(''):
const cancel = (close) => {
setValue('');
close();
};
This is my reusable component:
import {
Dialog,
DialogContent,
DialogContentText,
DialogTitle,
Divider,
Button,
DialogActions,
} from "#mui/material";
const Modal = ({ title, subtitle, children, isOpen, handleClose }) => {
return (
<Dialog open={isOpen} onClose={handleClose}>
<DialogTitle>{title}</DialogTitle>
<DialogContent>
<DialogContentText>{subtitle}</DialogContentText>
<Divider />
{children}
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="error">
Close
</Button>
</DialogActions>
</Dialog>
);
};
export default Modal;
Parent component where I use this here:
const [isOpen, setisOpen] = useState(false);
const [isOpenDialog, setIsOpenDialog] = useState(false);
const handleDialogOpen = () => {
setisOpen(true);
};
const handleDialogClose = () => {
setisOpen(false);
};
const handleOpen = () => {
setIsOpenDialog(true);
};
const handleClose = () => {
setIsOpenDialog(false);
};
<Modal
title="confirmation"
isOpen={isOpen}
children={sample}
handleClose={handleDialogClose}
/>
<Button
color="error"
onClick={
() => handleDialogOpen}
>
Delete
</Button>
It does not show any error in the console and the app does not crash. How can I fix this? Also how can I add a button where the user can say yes since at the moment the modal only have a buttin to close it
There's a lot to unpack here. Here's a solution:
import {
Dialog,
DialogContent,
DialogContentText,
DialogTitle,
Divider,
Button,
DialogActions
} from "#mui/material";
const Modal = ({ title, subtitle, children, isOpen, handleClose }) => {
const handleConfirm = () => {
alert("You Agreed!");
handleClose();
};
return (
<Dialog open={isOpen} onClose={handleClose}>
<DialogTitle>{title}</DialogTitle>
<DialogContent>
<DialogContentText>{subtitle}</DialogContentText>
<Divider />
{children}
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="error">
Cancel
</Button>
<Button onClick={handleConfirm} color="primary">
Agree
</Button>
</DialogActions>
</Dialog>
);
};
export default Modal;
Here's the parent:
import Modal from "./modal";
import { useState } from "react";
import { Button } from "#mui/material";
export default function App() {
const [isOpen, setisOpen] = useState(false);
const handleOpen = () => {
setisOpen(true);
};
const handleClose = () => {
setisOpen(false);
};
return (
<div className="App">
<Modal title="confirmation" isOpen={isOpen} handleClose={handleClose} />
<Button color="primary" onClick={handleOpen}>
I Agree
</Button>
</div>
);
}
Here's the sandbox:
I'm trying to create a notifications area. I show a notification icon, and when the user clicks on it, I show the list of notifications.
Here's a codesandbox
The problem is that I can't mix it with ClickAwayListener.
When I use ClickAwayListener it's not shown at all.
How should I fix this?
HeaderAction.js
import Tooltip from "#material-ui/core/Tooltip";
import Fade from "#material-ui/core/Fade";
import Collapse from "#material-ui/core/Collapse";
import React, { useState } from "react";
import ClickAwayListener from "#material-ui/core/ClickAwayListener";
import Icon from "#material-ui/core/Icon";
const HeaderAction = ({ icon, title, component }) => {
const Component = component || (() => <div>NA</div>);
const [showComponent, setShowComponent] = useState(false);
const handleClick = () => {
setShowComponent(!showComponent);
};
return (
<>
<Tooltip title={title || ""}>
<div onClick={() => handleClick()}>
<Icon>{icon}</Icon>
</div>
</Tooltip>
{/* This part is not working */}
{/* <ClickAwayListener onClickAway={() => setShowComponent(false)}>
<div>
<Fade in={showComponent}>
<div>
<Component />
</div>
</Fade>
</div>
</ClickAwayListener> */}
<Fade in={showComponent}>
<div>
<Component />
</div>
</Fade>
</>
);
};
export { HeaderAction };
When you click the icon button, handleClick is called and the showComponent state is set to true, but then onClickAway from ClickAwayListener is also called and set the showComponent state to false again. The fix is simple, don't let the onClickAway handler execute by stopping the propagation after clicking the button:
<div
onClick={(e) => {
e.stopPropagation();
handleClick();
}}
>
I'm using material ui autocomplete textfield in my project inside a dialog.
The problem is, when i set a defaultValue or a first value, you can see the placeholder moving on the opening of the dialog.
https://codesandbox.io/embed/material-ui-autocomplete-forked-xwd3k?fontsize=14&hidenavigation=1&theme=dark
Here is the code
import React from "react";
import ReactDOM from "react-dom";
import Autocomplete from "#material-ui/lab/Autocomplete";
import { TextField } from "#material-ui/core";
import DialogTitle from "#material-ui/core/DialogTitle";
import Dialog from "#material-ui/core/Dialog";
import Button from "#material-ui/core/Button";
import "./styles.css";
function App() {
const [open, setOpen] = React.useState(false);
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = (value) => {
setOpen(false);
};
return (
<>
<Dialog
onClose={handleClose}
aria-labelledby="simple-dialog-title"
open={open}
>
<DialogTitle id="simple-dialog-title">Set backup account</DialogTitle>
<Autocomplete
freeSolo
id="free-solo-demo"
defaultValue={"a"}
options={["a", "b", "c"]}
renderInput={(params) => (
<TextField
{...params}
label="freeSolo"
margin="normal"
variant="outlined"
fullWidth
/>
)}
/>
</Dialog>
<div>
<br />
<Button variant="outlined" color="primary" onClick={handleClickOpen}>
Open simple dialog
</Button>
</div>
</>
);
}
Is there a way to see the placeholder already fixed when the dialog is open? I have an other autocomplete that is with multiple, and this textfield is not giving me this error at all.
Add the following InputLabelProps to the TextField component.
<TextField
{...params}
InputLabelProps={{ // this part
shrink: true
}}
label="freeSolo"
margin="normal"
variant="outlined"
fullWidth
/>
If you check the implementation of the TextField component, you can see that the input label prop gets notched if the shrink parameter is truthy.
Edit: Which means that if the field becomes empty you will have to manage that yourself.
I want to create a Modal variant with and set the default width and background color (among other things). I can't find documentation that says exactly how to do it, but I figured using variants would be the way to go.
I've put my best attempt on Code Sandbox here: https://codesandbox.io/s/vigilant-germain-u3mkx?
Any suggestions would be welcome.
Add baseStyle in the Modal component instead of variants
import {
ChakraProvider,
Modal,
extendTheme,
Button,
useDisclosure,
ModalOverlay,
ModalContent,
ModalHeader,
ModalFooter,
ModalCloseButton,
ModalBody
} from "#chakra-ui/react";
import "./styles.css";
const theme = extendTheme({
components: {
Modal: {
baseStyle: (props) => ({
dialog: {
maxWidth: ["95%", "95%", "95%"],
minWidth: "95%",
bg: "#00ff00"
}
})
}
}
});
export default function App() {
const { isOpen, onOpen, onClose } = useDisclosure();
return (
<ChakraProvider theme={theme}>
<Button onClick={onOpen}>Open Modal</Button>
<Modal isOpen={isOpen} onClose={onClose} variant="wide">
<ModalOverlay />
<ModalContent>
<ModalHeader>Modal Title</ModalHeader>
<ModalCloseButton />
<ModalBody>
<p>Test</p>
</ModalBody>
<ModalFooter>
<Button colorScheme="blue" mr={3} onClick={onClose}>
Close
</Button>
<Button variant="ghost">Secondary Action</Button>
</ModalFooter>
</ModalContent>
</Modal>
</ChakraProvider>
);
}