I am using material UI backdrop and want to have some some tiny form inside of it. But whenever i click on its children the backdrop closes thanks to onClick which supposed to toggle the backdrop.
Is there any way how to stop backdrop onClick from triggering from inside backdrop (it's children) ?
I have tried to use useRef for elements inside but to me it seems crazy to have multiple referencies on elements and checking them in toggle function if it supposed to hide backdrop or not. Also i don't have access to some elements inside of the backdrop;
const handleBackdropToggle = e => {
console.log(e.currentTarget === backdropRef.current);
if (e.currentTarget === backdropRef.current) {
setOpen(!open);
}
};
const handleToggle = e => {
setOpen(!open);
};
<Backdrop
className={classes.backdrop}
open={open}
onClick={handleBackdropToggle}
ref={backdropRef}
>
<div className={classes.form}>
<CommonFormCard
noBorder={true}
onSubmit={onSubmit}
onBack={handleToggle}
submitButtonText={`Odeslat`}
>
<>
<h4>Od kdy má fotograf nafotit nemovitost?</h4>
<CommonForm formData={renderFormData} onChange={onChange} />
</>
</CommonFormCard>
</div>
</Backdrop>;
Rather than toggling your backdrop via onClick on the backdrop, you can use the Click away listener.
The main issue that you are likely experiencing is that you need to stop the propagation of click events in the form. The nature of DOM events is that they propagate up to all ancestors by default. You can prevent this with:
<div className={classes.form} onClick={e => e.stopPropagation()}>
I know I'm answering late. But this solution may prove most efficient.
Don't use onClick of Backdrop component. Instead, add a child button to close the backdrop. Now you can trigger children click events without needing to worry about event propagation to the backdrop parent.
Related
I am using Antd 4.x library. I have a Collapse and a popover that shows on Click of button on Collapse which has a Checkbox in it. I would like to Stop Propagation when checking/unchecking the checkbox, i.e. the Collapse opens/closes when checking/unchecking
Although when I click on Label of Checkbox the Collapse doesn't open/close but when the I do it on the checkable part of checkbox it happens.
I would like to Stop the open/close of Collapse when checking/unchecking of checkbox on popover
Demo Link to show the issue
TIA
You can wrapped your Panel extra content in a div and add onClick to stopPropagation. Also, you do not have to handle stopPropagation in Setting Button & Checkbox.
const onChange1 = (e: { target: { checked } }) => {
console.log(`checked = ${e.target.checked}`);
};
const genExtra = () => (
<div onClick={(e) => e.stopPropagation()}>
<Popover content={<Checkbox onChange={onChange1}>Checkbox</Checkbox>} title='Title'>
<SettingOutlined />
</Popover>
</div>
);
First of all, you have to understand that when an event occurs, the event always has an event source, that is, the object that caused the event. An event cannot be generated out of thin air. This is the occurrence of an event.
When the event occurs, the event will start to propagate. In your case, when we click the checkbox, a click event will be generated, but the checkbox cannot handle this event. The event must be propagated from the checkbox to reach the code that can handle the event. (for example, we assign a function name stopPropagation to the Fragment's onClick property, which is to let "stopPropagation" handle the Chekbox's click event).
import React, { Fragment } from "react";
function stopPropagation(e) {
//The stopPropagation() method of the Event interface prevents further propagation of the current event in the capturing and bubbling phases.
if (e && e.stopPropagation) {
e.stopPropagation();
} else {
//If it is IE browser
window.event.cancelBubble = true;
}
}
const genExtra = () => (
<Fragment onClick={(e) => stopPropagation(e)}>
<Popover
content={<Checkbox onChange={onChange1}>Checkbox</Checkbox>}
title="Title"
>
{/* <Button type="primary" shape="circle" icon={<SearchOutlined />} /> */}
<SettingOutlined
onClick={(event) => {
event.stopPropagation();
}}
/>
</Popover>
</Fragment>
);
For your reference: https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation
//This is dropdown component
const Dropdown: FC<any> = ({ list, item, title },props) => {
const isDisabled = item && item.users.length > 0 ? false : true;
const [show, setShow] = useState(false);
const toggleMenu = () => {
setShow(!show);
};
return (
<div>
<Button
title={title || "Action"}
onClick={toggleMenu}
iconName="downarrow"
iconPosition="left"
variant="outlined"
color="primary"
/>
)
The action menu is not getting closed even if I click somewhere on page, the menu
remains open until I explicitly click on the Action button again.
If you want the action menu to close when you click anywhere on the page using onClick won't help it. Use onBlur and use it on the button as -
<Button
title={title || "Action"}
onClick={toggleMenu}
onBlur={() => setShow(true)}
iconName="downarrow"
iconPosition="left"
variant="outlined"
color="primary"
/>
Or alternatively, what you can do is -
Create a reference to your outer div.
Add event listener mousedown (or click) to the document whenever this component appears on screen (eg. mount) and also don’t forget to remove the event on unmount too.
Inside the event (handleClick) this.{Any ref name you give}.contains(e.target) will return true if whatever you are clicking is inside the “node” ref.
Now you have it, you can now do whatever you feel like, close the modal, close the dropdown menu list, anything is allowed.
The above 4 points were taken from the article - https://medium.com/#pitipatdop/little-neat-trick-to-capture-click-outside-react-component-5604830beb7f.
Say I want to stop the event from propagating upon exit from the modal, for example when clicking on the background or the exit button which will close the modal. But then it'll redirect me to the (parent)? onClick event upon exiting.
<Modal onHide={(e) => {
e.stopPropagation();
setShow(false);
...
}}>
<Modal/>
The above does not work. I also tried onExit which also doesn't work.
The workaround was to use a div element around the Modal to control the event.
<div
onClick ={(e) => e.preventPropagation()}
>
<Modal>
<Modal/>
</div>
So I have this modal that is wrapped with an entire background div. My issue is that I added a close function on the background, so no matter where I click, it will close the modal.
I would like to have the useRef only target the background div and not work if I click any of the children inside of it
Here is the code
const modalRef = useRef();
const closeModal = e => {
if (modalRef.current.contains(e.target)) {
setShowModal(false);
}
}
return (
<>
{showModal ? (
<Background onClick={closeModal} ref={modalRef}>
<animated.div style={animation}>
<ModalWrapper showModal={showModal}>
<div>hi</div>
<CloseModalButton
aria-label='Close modal'
// onClick={() => setShowModal(!showModal)}
/>
</ModalWrapper>
</animated.div>
</Background>
) : null}
</>
);
};
So right now the ref is attached to the background, but if I console.log(modalRef.current) it will show me the entire jsx with all my children divs inside, but I only want to target the outside div aka the background
So whenever I click outside of my modal it will close
Note: when I console.log(modalRef.current) this is what shows up in the console aka my entire JSX
I'm also using styled-components, so I only want to target the top div which I called Background but shows sc-bdnylx iEsAwc so I have no idea how to target it since it doesn't have any ids or classNames
I tried to add this console.log(modalRef.current.children[0]) but when I implemented it into my function, it didn't work properly. This console.log does only show the divs below my Background div, but I haven't found anything about targeting just the Background only
You don't actually need to use refs here. Just add onClick={e => e.stopPropagation()} to one of the divs inside Background, like on ModalWrapper. It'll stop the click from passing through.
So basically i have a parent component which uses a child button component. Basically currently when the input validation is not correct it will keep the button disabled. However now I have tried to disable the button on click. The button is currently a pure component and i started to use hooks but not sure how i can still get the validation running.
Code is below
<ChildButton
onClick={() => {
this.checkSomething= this.checkCreds();
}}
enabled={this.validateInput()}
/>
My pure component currently looks like this:
export function AButton({ onClick, enabled, text }) {
const [disabled, setDisabled] = useState(!enabled);
function handleClick() {
setDisabled(!disabled);
//onClick();
}
return (
<Button
style={{ display: "block", margin: "auto" }}
id="next-button"
onClick={handleClick}
disabled={disabled}
>
{text}
</Button>
);
}
So i can get the disable button to work in both scenairos. As the enabled is always being passed down into this pure component so need to keep setting state of it.
I ended up using useEffect from react hooks
useEffect(() => setDisabled(!enabled), [enabled]);
This will check every time the enabled props is updated from the parent. Similar to how componentDidUpdate would work