ionic-team / stencil

A toolchain for building scalable, enterprise-ready component systems on top of TypeScript and Web Component standards. Stencil components can be distributed natively to React, Angular, Vue, and traditional web developers from a single, framework-agnostic codebase.
https://stenciljs.com
Other
12.59k stars 789 forks source link

Event handler in JSX + TS (Preact). Issue with generated typing #2528

Open nathan-barrett opened 4 years ago

nathan-barrett commented 4 years ago

Stencil version:

 @stencil/core@<1.11.3>

I'm submitting a:

[x] bug report [ ] feature request [ ] support request => Please do not submit support requests here, use one of these channels: https://stencil-worldwide.herokuapp.com/ or https://forum.ionicframework.com/

Current behavior: I have a component with an EventEmitter, called Dropdown. According to the docs and the generated typefile, i should be able to access the event handle using camel-case: <Dropdown onDropdownSelect={handler}> in JSX, but the event is never called.

Although if i use ondropdownSelect the event fires. I have checked in the components.d.ts file, and the event is typed as onDropDown, so if i use the handler that works, I get a TS error.

Expected behavior:

I would expect that the event handler would be the same as the type that is created in the types file.

Steps to reproduce:

Related code: Stencil component

@Component({
  tag: 'dropdown',
})
export class Dropdown {
  @Event() dropdownSelect!: EventEmitter<string>;

  ...

  protected handleSomething(value: string) {
    this.dropdownSelect.emit(value);
  }
}

preact doesn't work

<dropdown onDropdownSelect={ev => this.someMethod(ev)} />

works

<dropdown ondropdownSelect={ev => this.someMethod(ev)} />

Other information:

paulcpederson commented 4 years ago

An update on this issue, we were able to work around it by leveraging the custom docs output and generating an additional typings file specifically for preact:

https://github.com/Esri/calcite-design-system/blob/main/packages/calcite-components/support/preact.ts

This generates the following typings file:

import { JSXInternal } from "preact/src/jsx";
import { JSX } from "./components";

declare module "preact/src/jsx" {
  namespace JSXInternal {
    interface IntrinsicElements {
      "my-component": Omit<JSX.MyComponent, "onMyComponentEventName"> & JSXInternal.HTMLAttributes<HTMLMyComponentElement> & {
        "onmyComponentEventName"?: (event: CustomEvent<any>) => void;
      }
  }
}

You import the typings from the normal component ts, then augment intrinsic elements by declaring the tag names. Any events also must have their case changed so the first letter of the event name is lowercase.

It would be great if these typings were part of the standard stencil compiler as it was difficult to get up and running in a typescript + preact project.

christian-bromann commented 2 months ago

@nathan-barrett thanks for raising the issue and @paulcpederson for providing a workaround.

The Stencil team currently has a lot of competing priorities and can't promise to be able to take a look at this anytime soon. We recommend to get involved and help us resolve this bug by providing a pull request with a fix. We are happy to provide necessary guidance and appreciate any help!