solidjs / solid-docs-legacy

OLD documentation for SolidJS and related packages, replaced by https://github.com/solidjs/solid-docs-next
https://www.solidjs.com/
MIT License
188 stars 151 forks source link

stopPropagation on the parent element affects event handling on the child #204

Open w1ndy opened 2 years ago

w1ndy commented 2 years ago

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

Additional context

No response

ryansolid commented 2 years ago

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.

LiQuidProQuo commented 2 years ago

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

w1ndy commented 2 years ago

@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?

ryansolid commented 2 years ago

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.

w1ndy commented 2 years ago

@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?

ryansolid commented 2 years ago

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

ryansolid commented 2 years ago

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