Ant Design: prevent closing modal conditionally when onOk is called - reactjs

I'm using Ant Design v4.22.4 and use Model through useModal.
I want to keep the modal open conditionally when onOk function is called (when ok button is clicked`. Is there way to prevent closing the modal?

Yes you can do this, onOK function expects a function that changes the visibility state, here is a sample code:
import { Button, Modal } from 'antd';
import React, { useState } from 'react';
const App = () => {
const [isModalVisible, setIsModalVisible] = useState(false);
const showModal = () => {
setIsModalVisible(true);
};
const handleOk = () => {
setIsModalVisible(true);
};
const handleCancel = () => {
setIsModalVisible(false);
};
return (
<>
<Button type="primary" onClick={showModal}>
Open Modal
</Button>
<Modal title="Basic Modal" visible={isModalVisible} onOk={handleOk} onCancel={handleCancel}>
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
</Modal>
</>
);
};
export default App;
With this, whenever the user clicks on the OK button, the modal still remains visible.

Related

using a Popconfirm from antd to confirm the closing of a modal?

I am trying to use a popconfirm of ant design to confirm the closing of a modal, the following code I get the popconfirm to fire and the modal to close, but the popconfirm stays open.
does anyone have any idea how to make the popconfirm close when it is confirmed by giving it yes ?
import { Modal, Popconfirm } from 'antd';
import { useState } from 'react';
export const Ensayo=()=> {
const [open, setOpen] = useState(false);
const [popupOpen, setPopupOpen] = useState(false);
const showModal = () => {
setOpen(true);
};
const handleCancel = () => {
setPopupOpen(true);
};
const handlePopupConfirm = () => {
setOpen(false);
setPopupOpen(false);
};
const handlePopupCancel = () => {
setPopupOpen(false);
};
return (
<div>
<button type="button" onClick={showModal}>
Open Modal
</button>
<Modal
title="Basic Modal"
open={open}
onCancel={handleCancel}
>
<p>Some contents...</p>
<Popconfirm
title="Are you sure you want to close this modal?"
open={popupOpen}
onConfirm={handlePopupConfirm}
onCancel={handlePopupCancel}
okText="Yes"
cancelText="No"
/>
</Modal>
</div>
);
}
I have tried to add the popupOpen condition as a condition for the popconfirm rendering but it doesn't work with that condition it never triggers the popconfirm.
You can move the <Popconfirm> component outside the <Modal>
check the following example
import { Modal, Popconfirm } from "antd";
import { useState } from "react";
export const Ensayo = () => {
const [open, setOpen] = useState(false);
const [popupOpen, setPopupOpen] = useState(false);
const showModal = () => {
setOpen(true);
};
const handleCancel = () => {
setPopupOpen(true);
};
const handlePopupConfirm = () => {
setOpen(false);
setPopupOpen(false);
};
const handlePopupCancel = () => {
setPopupOpen(false);
};
return (
<div>
/* Popconfirm moved here */
<Popconfirm
title="Are you sure you want to close this modal?"
open={popupOpen}
onConfirm={handlePopupConfirm}
onCancel={handlePopupCancel}
okText="Yes"
cancelText="No"
/>
<button type="button" onClick={showModal}>
Open Modal
</button>
<Modal title="Basic Modal" open={open} onCancel={handleCancel}>
<p>Some contents...</p>
</Modal>
</div>
);
};
export default Ensayo;
Output:

ReactJS Modal Window onClick

My ReactJS Modal Window do not work.
Here is code:
import React from 'react';
import './Modal.css';
import Button from 'react-bootstrap/Button';
const Modal = ({ handleClose, show, children }) => {
const showHideClassName = show ? "modal display-block" : "modal display-none";
return (
<div className={showHideClassName}>
<section className="card modal-main">
{children}
<div className="clear"></div>
<Button onClick={handleClose}>
Close
</Button>
</section>
</div>
);
};
export default Modal;
And here is code in my component:
function modalState(state) {
return state;
};
<Modal show={modalState(setModal)} handleClose={modalState(false)}>
{
<div></div>
}
</Modal>
And if I click Add user button then nothing happens:
<Button variant="primary" size="sm" onClick={() => {
setModal = true;
modalState(setModal);
}}>Add User</Button>{' '}
What should I doing wrong?
Try to use useState hook.
Your Modal component.
import { useState } from 'react';
import './Modal.css';
import Button from 'react-bootstrap/Button';
const Modal = ({ show, children }) => {
const [modalState, setModalState] = useState(show);
const showHideClassName = show ? "modal display-block" : "modal display-none";
return (
<div className={showHideClassName}>
<section className="card modal-main">
{children}
<div className="clear"></div>
<Button onClick={() => setModalState(false)}>
Close
</Button>
</section>
</div>
);
};
export default Modal;
And your component where calls Modal component.
import { useState } from 'react';
import Modal from './path/Modal';
const CustomComponent = () => {
const [modalState, setModalState] = useState(false);
return (
<>
<Modal show={modalState}>
{
<div></div>
}
</Modal>
<Button
variant="primary" size="sm"
onClick={() => setModalState(true)}
>
Add User
</Button>
</>
);
}
export default CustomComponent;
But please note that this would be just a temporary solution based on your current codes. If you want a better and permanent solution, I'd like to recommend to implement the global state management thru your whole codebase using Redux or Recoil.
In the onclick event useState set is not done to set the value of the Modal
setModal({modal:true})
And
<Modal show={modal} handleClose={modalState(false)}>
{
<div></div>
}
</Modal>
I think if you do this it will work.
const [isVisibleModal, setVisibleModal] = useState(false); // <- add
function closeModal() {
setVisibleModal(!isVisibleModal);
};
<Modal show={isVisibleModal} handleClose={closeModal}>
{
<div></div>
}
</Modal>
<Button
variant="primary"
size="sm"
onClick={() => setVisibleModal(true)}
>
Add User
</Button>
Hope this helps you!
You should use setVisibleModal function same page like this code
import React, { useState } from 'react';
const YourComponent = () => {
const [isVisibleModal, setVisibleModal] = useState(false); // <- add
function closeModal() {
setVisibleModal(!isVisibleModal);
};
return (
<>
<Modal show={isVisibleModal} handleClose={closeModal}>
{
<div></div>
}
</Modal>
<Button
variant="primary"
size="sm"
onClick={() => setVisibleModal(true)}
>
Add User
</Button>
</>
)
}
export default YourComponent;

How to resize width of Ant Design modal based on different screen sizes?

I just want the max width of the modal to be 1200px and then 100% width if screen width is less than 1200px. Ive tried using style={{maxWidth: "1200px"}} but that doesn't work and there is no explanation of how to do this in the Ant Design docs. Any help is appreciated!
import React, { useState } from 'react';
import { Modal, Button } from 'antd';
const App = () => {
const [isModalVisible, setIsModalVisible] = useState(false);
const showModal = () => {
setIsModalVisible(true);
};
const handleOk = () => {
setIsModalVisible(false);
};
const handleCancel = () => {
setIsModalVisible(false);
};
return (
<>
<Button type="primary" onClick={showModal}>
Open Modal
</Button>
<Modal
style={{maxWidth: "1200px"}}
title="Basic Modal"
visible={isModalVisible}
onOk={handleOk}
onCancel={handleCancel}
>
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
</Modal>
</>
);
};
ReactDOM.render(<App />, mountNode);
Add this code and use maxModalSize value
const [maxModalSize, setMaxModalSize] = useState(1200);
const resize = () => {
const maxSize = Math.min(1200, window.innerWidth);
setMaxModalSize(maxSize);
};
useEffect(() => {
window.addEventlistener("resize", resize);
return () => window.removeEventlistener("resize", resize);
});

Material UI Dialog turned to Hook flickering

I'm trying to turn Material UI's dialog into a "useDialog" hook so it keeps track of it's own open state.
Unfortunately I've encountered a problem that whenever I update a state further up the hierarchy, the dialog flickers and I'm not exactly sure why and how to circumvent it. I feel like a useRef is needed there somewhere, but I'm not sure. Here's a reproduced minimal example: https://codesandbox.io/s/flickering-dialog-minimal-example-ehruf?file=/src/App.js
And the code in question:
import React, { useState } from "react";
import {
Button,
Dialog,
DialogActions,
DialogContent,
DialogTitle
} from "#material-ui/core";
export default function App() {
const [openDialog, Dialog] = useDialog();
const [counter, setCounter] = useState(0);
return (
<div>
<Dialog title="Hello">
<div>{counter}</div>
<button onClick={() => setCounter(counter => counter + 1)}>
Increase
</button>
</Dialog>
<button onClick={openDialog}>Open dialog</button>
</div>
);
}
const useDialog = () => {
const [open, setOpen] = useState(false);
const handleClose = () => {
setOpen(false);
};
const someDialog = ({ title, children }) => {
return (
<Dialog open={open} onClose={handleClose}>
<DialogTitle>{title}</DialogTitle>
<DialogContent>{children}</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="primary">
Close
</Button>
</DialogActions>
</Dialog>
);
};
return [
() => {
setOpen(true);
},
someDialog
];
};
The reason the dialog flickers is that a new Dialog component is created on every render(as a result of state change) in App. The old Dialog is unmounted and replaced by the new Dialog.
A rule of thumb is you should never define components while rendering.
That's why I suggest you separate your custom dialog component from useDialog hook:
const MyDialog = ({ open, handleClose, title, children }) => {
return (
<Dialog open={open} onClose={handleClose}>
<DialogTitle>{title}</DialogTitle>
<DialogContent>{children}</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="primary">
Close
</Button>
</DialogActions>
</Dialog>
);
};
You can, however, keep some of the logic inside useDialog and reuse them:
const useDialog = () => {
const [open, setOpen] = useState(false);
const openDialog = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
const props = {
open,
handleClose
};
return [openDialog, props];
};
More about why returning components from hook can be a bad idea.
Custom hooks are not made for returning a component, instead they are used to create a common logic which will be shared by different components.
In your case I would suggest you to create a common component for your dialog. And use this component wherever you want. Like this:
<CustomDialog open={open}>
// Your jsx here
</CustomDialog>
const CustomDialog = ({children}) => {
return <Dialog open={open} onClose={handleClose}>
<DialogTitle>{title}</DialogTitle>
<DialogContent>{children}</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="primary">
Close
</Button>
</DialogActions>
</Dialog>
}
For more information about custom hooks:
https://reactjs.org/docs/hooks-custom.html
To whomever finds this issue because of my mistake. I was using a styled Dialog and defined the styled Dialog inside the functional component. Just put the custom styling outside of any component.
// This needed to be outstide of the BetterDialog component
const CustomDialog = styled(Dialog)({
"& .MuiDialog-paper": {
zIndex: 90
}
})
...
function BetterDialog(props: BetterDialogProps) {
...

In reactjs modal close button is not working

I am use bootstrap modal in reactjs project. Here is the link of package which i have installed in my project: https://www.npmjs.com/package/react-responsive-modal
When, I click on open the modal button then it is working, but when i click on close button then close button is not working. I am using the hooks in my project. Below, I have mentioned my code:
import React, { useState } from 'react'
import Modal from 'react-responsive-modal'
const Login = () => {
const [open, openModal] = useState(false)
const onOpenModal = () => {
openModal({open: true})
};
const onCloseModal = () => {
openModal({open: false})
};
return(
<div>
<h1>Login Form</h1>
<button onClick={onOpenModal}>Open modal</button>
<Modal open={open} onClose={onCloseModal} center>
<h2>Simple centered modal</h2>
</Modal>
</div>
)
}
export default Login;
The issue is because, you are setting object in state,
openModal({open: true})
This will store object in state.
setState require's direct value which needs to be change, your setState must be this,
const onOpenModal = () => {
openModal(!open) //This will negate the previous state
};
const onCloseModal = () => {
openModal(!open) //This will negate the previous state
};
Demo
You can simplify your code and just use 1 change handle for your modal,
const Login = () => {
const [open, openModal] = useState(false)
const toggleModal = () => {
openModal(!open)
};
return(
<div>
<h1>Login Form</h1>
<button onClick={toggleModal}>Open modal</button>
<Modal open={open} onClose={toggleModal} center>
<h2>Simple centered modal</h2>
</Modal>
</div>
)
}
Demo
Your naming of the model hook is misleading and you're using the setState part of the Hook wrong, probably mixing it up with the this.setState convention for non-Hook React code.
import React, { useState } from 'react'
import Modal from 'react-responsive-modal'
const Login = () => {
const [modalOpen, setModalOpen] = useState(false)
const onOpenModal = () => {
setModalOpen(true)
};
const onCloseModal = () => {
setModalOpen(false)
};
return(
<div>
<h1>Login Form</h1>
<button onClick={onOpenModal}>Open modal</button>
<Modal open={modalOpen} onClose={onCloseModal} center>
<h2>Simple centered modal</h2>
</Modal>
</div>
)
}
export default Login;

Resources