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

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

Open
theengineear opened this issue Nov 4, 2022 · 3 comments
Open

Comments

@theengineear
Copy link
Collaborator

theengineear commented Nov 4, 2022

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:

  • It may be expected behavior at this point (as it exists in other templating engines)

Why we might not add it:

  • It’s redundant — you can already achieve this behavior.
  • It adds complexity / size to the base element.
  • It adds an additional runtime check — this may or may not be a performance drawback.
  • In many years of leveraging other templating engines — we've not once used this functionality.
  • Integrators can choose to use other templating engines like lit-html or uhtml if this is desired.

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
Copy link
Collaborator Author

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
Copy link

chen-ye commented Dec 6, 2022

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
Copy link
Collaborator Author

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.

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

No branches or pull requests

2 participants