solid-docs icon indicating copy to clipboard operation
solid-docs copied to clipboard

stopPropagation on the parent element affects event handling on the child

Open w1ndy opened this issue 3 years ago • 7 comments

Describe the bug

I'm trying to implement a 'onClickOutside' directive. Somehow when I stop the click event propagation on the parent element in the directive, the onClick handler on the child element no longer works. A bug reproduction is provided below.

Your Example Website or App

https://playground.solidjs.com/?hash=1327590733&version=1.4.1

Steps to Reproduce the Bug or Issue

Click on the click me button.

Expected behavior

Expected console output: works followed by stopped, indicating that the click event is received by the button first, and then bubbled up to the onClickOutside directive, which stops the event propagation to the document.

Current console output: stopped. Only the directive is getting the click event.

Screenshots or Videos

No response

Platform

  • OS: Windows
  • Browser: Firefox
  • Version: 105.0.3

Additional context

No response

w1ndy avatar Oct 16 '22 15:10 w1ndy

Yeah this is because of the timing as on element events will run before the event delegation. This is similar to React. Trying to decide what the best answer to tell you is. You can use Solid's event listener helper directly. Like this: https://playground.solidjs.com/?hash=1027922061&version=1.4.1.

But part of me would like to point to something that feels more idiomatic. Probably some ability to extend element with native props.. like basically using Solid's internal spread helper, but then I'm reminded this is just more efficient even if not documented.

ryansolid avatar Oct 16 '22 20:10 ryansolid

for click outside, you can prioritize the detection handler by "capturing" the event.

  document.addEventListener("click", handleClick, { capture: true });

https://playground.solidjs.com/?hash=1020624715&version=1.4.1

LiQuidProQuo avatar Oct 16 '22 21:10 LiQuidProQuo

@ryansolid @LiQuidProQuo Thanks for the tips! I tried both examples, and they worked correctly (although I had to use stopImmediatePropagation with Ryan's example).

However, I'm still struggling to understand why stopPropagation during the event bubbling phase on the parent element will prevent the onClick handler on the target element from being executed... The order of handler execution should be capturing -> target -> bubbling, right? So, why the event handler on the target element is not executed at all?

w1ndy avatar Oct 17 '22 09:10 w1ndy

We delegate to the document. It's a performance trick, works well with Portals, and helps with some fun hydration stuff. Many of Solid's events, including mouse, pointer, input events are all attached to the document. So adding a direct event handler actually triggers before any added in the JSX when bubbling. This implicit delegation is common in a number of frameworks including React.

ryansolid avatar Oct 17 '22 09:10 ryansolid

@ryansolid Good to know, thanks! Shall we add some text to docs (maybe this page since the example provided is to add event listeners?) to remind people about the order of event handler execution?

w1ndy avatar Oct 17 '22 15:10 w1ndy

Yeah delegation is mentioned but not explained at all. It belongs under on__ definitely.

ryansolid avatar Oct 17 '22 16:10 ryansolid

This is completely a docs issue. I'm going to move it there so we can be reminded to put in the right mention.

ryansolid avatar Oct 18 '22 17:10 ryansolid

Deploy Preview for solid-docs ready!

Name Link
Latest commit 5b95bbff9e8dd186cc2e29dc987122d814ec7172
Latest deploy log https://app.netlify.com/sites/solid-docs/deploys/63e1563706e0a70008946353
Deploy Preview https://deploy-preview-204--solid-docs.netlify.app
Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site settings.

netlify[bot] avatar Feb 05 '23 13:02 netlify[bot]