Netflix / x-element

A dead simple starting point for custom elements.
Apache License 2.0
28 stars 12 forks source link

Discussion: Enable support for event bindings in Template Engine. #120

Open theengineear opened 1 year ago

theengineear commented 1 year ago

Authors can already leverage the listeners block or listen / unlisten methods in connectedCallback / disconnectedCallback to manage event handling. An event binding would potentially provide a more ergonomic solution, maybe.

Why we might add it:

Why we might not add it:

Proposal

Users would be able to declare something like the following to add an event handler:

static template(html) {
  return ({ onClick }) => {
    return html`<button type="button" @click="${onClick}">Click Me</button>`;
  };
}
theengineear commented 1 year ago

I'm opposed to adding this functionality, but I wanted to open this issue up since this behavior is common in other templating engines.

chen-ye commented 1 year ago

I'll chime in here to say that one thing that template event binding allows for is the ability to bind to dynamically instantiated elements--such as sub-elements in a repeat/map.

For the most part, the same thing can logically be achieved using event delegation or custom events that are listened to at the host level, but there are some instances where directly binding is substantially more ergonomic.

For example, consider the following:

<table id="table">
  ${rows.map((row) => html`
    <tr>
        <th id=${row.id} @click=${setActiveRow}>
            <label>${row.label}<label><x-indicator enabled=${row.active}></x-indicator>
        </th>...
    </tr>`}
</table>

In order to do something logically similar using listen/unlisten, you could delegate the click handler to #table--however, because the row headers contain sub elements, the handler would need to crawl the evt.composedPath() in order to get to the th--which is both less efficient, and more brittle.

Alternatively, you could create a custom element for the table row header cell, and rely on css in order to make it behave the same as a native <th> element--however that's a substantial amount of boilerplate to just enable individual table row headers to be clicked.

In addition, I'll add that I personally prefer template event binding because it's one fewer opportunity for a mapping error--it's always possible to typo a listen call or overlook it when refactoring, but it's impossible to disassociate a template event binding, given that it is on the bound element markup itself.

theengineear commented 1 year ago

Hi @chen-ye! Thanks for your comment, it definitely helps weigh pros / cons to these choices. I'll add another argument to my top comment. Mainly, I will also add that the move to have x-element bundle its own templating engine is not meant to force everyone to use it. Rather, it's meant to provide basic functionality out of the box, but be architected in such a way that folks can plugin whatever templating engine they need. So, for your use-case, it's completely ok for you to continue using another library like lit-html or uhtml as your templating engine of choice.