-
Notifications
You must be signed in to change notification settings - Fork 319
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
[feature request] create an listen decorator for host listeners #1165
Comments
Not sure whether you'd want to allow |
My attempt at this: type EventHandler = (event: Event) => boolean | void;
interface CustomElement extends Element {
connectedCallback: () => void;
disconnectedCallback: () => void;
}
export function listen(eventName: string) {
return (target: CustomElement, key: string): void => {
const { connectedCallback, disconnectedCallback } = target;
let eventHandler: EventHandler;
target.connectedCallback = function () {
connectedCallback.call(this);
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
eventHandler = (event: Event) => (this as any)[key](event);
this.addEventListener(eventName, eventHandler);
};
target.disconnectedCallback = function () {
this.removeEventListener(eventName, eventHandler);
disconnectedCallback.call(this);
};
};
} |
We've considered this before and haven't done it yet mainly because Where we've added decorators so far have been cases where we need to transform an existing JS construct (@Property and @internalProperty) or we want a declarative form for analysis (@CustomElement) or a declarative form to have a spot to hang type information (@query and friends). I'm not sure if Since we already had a controller API in lit-next that can hook lifecycles, it seems like all we need to allow |
They're also good to prevent spots where anti-patterns may arise like memory leaks from element references due to listeners or when I was speaking to a community member about the This not to mention that internally we aren't even allowed to use |
Coming back to this because of the frustration the following pattern gives me: @customElement('my-element')
class MyElement extends LitElement {
private boundOnClick = (_e: MouseEvent) => {}; // hopefully some type that satisfies addEventListener in TS
connectedCallback() {
super.connectedCallback();
this.boundOnClick = this.onClick.bind(this);
// internally at google the line above has to be
// this.boundOnClick = (e: mouseEvent) => (this.onClick(e));
// because we are not allowed the use of `bind`
this.addEventListener('click', this.boundOnClick, {capture: true});
}
disconnectedCallback() {
super.disconnectedCallback();
this.removeEventListener('click', this.boundOnClick);
}
onClick(e: MouseEvent) {...}
} as opposed to something like: @customElement('my-element')
class MyElement extends LitElement {
@eventOptions({capture: true}) // tbh not sure if the implementation of eventOptions would allow this
@hostListener('click', {removeOnDisconnect: true, bind: true}) // these likely could be default
onClick(e: MouseEvent) {...}
} |
Closing in favor of lit/rfcs#11 since this should be included and/or covered by that proposal. |
Description
@listen
decorator to declaratively add event listeners to host.bind
and listener references is annoying@listen
Acceptance criteria
What the card must do in order to accept it as complete. Acceptance Criteria must be concrete or measurable.
A TS decorator to add event listeners to host.
The text was updated successfully, but these errors were encountered: