stencil icon indicating copy to clipboard operation
stencil copied to clipboard

bug: custom events on non-stencil element not working

Open trusktr opened this issue 1 year ago • 3 comments

Prerequisites

Stencil Version

4.22.2

Current Behavior

I am unable to listen to a custom event on a non-stencil element (f.e. a <div>) in JSX. Instead Stencil writes an attribute to DOM after stringifiying the passed function.

Expected Behavior

There should be a way to do this.

System Info

N/A

Steps to Reproduce

Put this component in a Stencil app.

import { Component, h, Prop } from '@stencil/core';

@Component({ tag: 'app-root', styleUrl: 'app-root.css', shadow: true })
export class AppRoot {
  div!: HTMLElement;

  componentDidLoad() {
    this.div.dispatchEvent(new CustomEvent('customEvent')); // expect "customEvent" to be logged to console.
  }

  render() {
    return (
      <div
        ref={el => (this.div = el)}
        // @ts-ignore
        oncustomEvent={() => console.log('customEvent')}
      ></div>
    );
  }
}

Instead of customEvent being logged, the DOM will have this in it (see element inspector):

Image

Code Reproduction URL

...

Additional Information

Other JSX frameworks support this. For example,

  • React 19 -> onmYeVeNt={fn} listens for an event named mYeVeNt (case sensitive) on any custom elements.
  • Similar with Preact.
  • Solid.js and Pota both have explicit on:wHaTeVeR={} prop syntax (case sensitive) which will always listen to the given event.

The reason it would be good to have this is then users do not need to do a dance with ref.

Having to escape out of one's favorite framework's template system is not desirable.

trusktr avatar Feb 17 '25 08:02 trusktr

If I change it from <div to <foo-bar it will set the JS property instead of an attribute, but still not listen to a customEvent.

Based on this, it seems that if we use a <custom-element> from another framework (for example, Lit, Atomico, Enhance, Lume Element, etc) we won't be able to listen for events on those elements in JSX, and will have to undesirably escape out of Stencil's JSX into plain JS.

trusktr avatar Feb 17 '25 08:02 trusktr

@trusktr what happens if you change the listener toonCustomEvent (with a capital 'C')? I think stencil, rightly or wrongly, checks for on{UPPERCASELETTER}whatever for event handlers.

johnjenkins avatar Feb 17 '25 10:02 johnjenkins

https://codesandbox.io/p/devbox/custom-event-listener-n33n9r

Image

I think it's working?

johnjenkins avatar Feb 18 '25 16:02 johnjenkins