Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

event handlers are unbound when called with forwarded DOM events from child components #6310

Closed
HartS opened this issue May 8, 2021 · 5 comments · Fixed by #6417
Closed

Comments

@HartS
Copy link

HartS commented May 8, 2021

Describe the bug
this is undefined in event handlers, when handling a DOM event which has been forwarded from a child component

Logs
See repro

To Reproduce
The bug can be easily reproduced in the DOM Event Forwarding section of the tutorial. Click Show me, then replace the handleClick definition with:

	function handleClick(event) {
		alert(this);
	}

This caused confusion later in the tutorial, in the Lifecycle/tick section, where this in a handler refers to event.target.

Expected behaviour
Unless this is intentional, I would expect consistency in how event handlers can be used regarding this. On the other hand, if using this from event handlers is discouraged, the above-mentioned tick section in the tutorial could use event.target instead

Additional Context
A discord user pointed me to

export function bubble(component, event) {
const callbacks = component.$$.callbacks[event.type];
if (callbacks) {
callbacks.slice().forEach(fn => fn(event));
}
}
where it appears the callbacks for the component events are invoked. If event here is the original DOM event, it may be as simple as calling the callback in the context of event.target:

fn.call(event.target, event)

In the event that event.target is undefined, we're back to where we started (this is undefined)

@Prinzhorn
Copy link
Contributor

Prinzhorn commented May 10, 2021

I'm not an expert here, but here's what I'm seeing:

In the tick example you're binding the event directly on <textarea> so you know what's happening and this behaves as expected. But I agree that it shouldn't use this there since it's also common to use arrow functions as event handlers and I personally always use event.target.

When you are using the <CustomButton> component, you have no idea what this even means. It could be a forwarded event, but you don't know from what type of element. But it could very well be a dispatch('click') without any DOM involved. What should this be then? It might make sense to have this point to the CustomButton instance?

So I'm with you that this should be discouraged I guess.

@bluwy
Copy link
Member

bluwy commented May 13, 2021

@Prinzhorn This issue is about preserving the this value for DOM forwarded events, so it matches the behavior of directly binding the event in the same component. Custom dispatched events would be expected to have this be undefined.

But yeah, this is just confusing in general.

@Prinzhorn
Copy link
Contributor

Prinzhorn commented May 13, 2021

@bluwy what I meant is that a consumer of CustomButton does not know that it is a forwarded event. That's internal information. A realistic example would be a Slider component where the first iteration simply forwards the click event. But then in a later version custom custom click is triggered only when the cursor hasn't moved a certain threshold, so that sliding a slide doesn't also trigger the click. A consumer of Slider shouldn't care about this internal change. Hence you cannot rely on the internal information that this was originally a forwarded event. Does that make sense?

@bluwy
Copy link
Member

bluwy commented May 14, 2021

@Prinzhorn I'm not sure if that's true. One way or another, the consumer of the component would need to know if it's a forwarded DOM event or a dispatched event. This can't be hidden internally since the Event object is being interacted by the consumer.

In case of a forwarded DOM event, the event type would be e.g. MouseEvent, while a dispatched event, it would be a CustomEvent. Both are of completely different shape and it would be a breaking change if you decide to swap between the two.

@Conduitry
Copy link
Member

this should be getting bound as part of forwarded/bubbled events now in 3.38.3.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants