From 315531e488cc0e4ee61170941774d1944aa28063 Mon Sep 17 00:00:00 2001 From: Nolan Lawson Date: Thu, 19 Jan 2023 14:14:49 -0800 Subject: [PATCH 1/6] RFC: Declarative root element --- text/0000-declarative-root.md | 276 ++++++++++++++++++++++++++++++++++ 1 file changed, 276 insertions(+) create mode 100644 text/0000-declarative-root.md diff --git a/text/0000-declarative-root.md b/text/0000-declarative-root.md new file mode 100644 index 00000000..7b2211cb --- /dev/null +++ b/text/0000-declarative-root.md @@ -0,0 +1,276 @@ +--- +title: Declarative root element +status: DRAFTED +created_at: 2022-01-19 +updated_at: 2022-01-19 +champion: Nolan Lawson (nolanlawson) +pr: https://github.com/salesforce/lwc-rfcs/pull/72 +--- + +# Declarative root element + +## Summary + +Provides a declarative way to apply reactive attributes, classes, and event listeners to the root (host) element. + +## Basic example + +In a component's template HTML file: + +```html + +``` + +Result: + +```html + + #shadow-root +

Hello world

+
+``` + +Classes, attributes, and event listeners are applied from the `` element to the +root `` element. (The event listener is not shown above.) + +## Motivation + +A common pattern in LWC components is something like this: + +```js +export default class extends LightningElement { + connectedCallback() { + this.template.host.classList.add('my-class'); + } +} +``` + +Developers may want to add a class, set an attribute, or add an event listener to the root (host) element +of the component. Today there is no declarative way to do this, so they resort to doing it manually in the +`connectedCallback`, `constructor`, or `renderedCallback`. + +This has several downsides: + +1. It does not work well with SSR, where it would require shims for DOM APIs like `classList`, `setAttribute`, etc., where `connectedCallback` timings [may differ](https://github.com/salesforce/lwc/issues/3009) between SSR and DOM, and where `renderedCallback` doesn't fire at all. +2. It is not easy to make it reactive, e.g. to set a class that updates based on a `@track`ed property. + +Prior art in other frameworks: + +- Stencil: [`` functional component](https://stenciljs.com/docs/host-element) +- Angular: [`@HostBinding`](https://angular.io/api/core/HostBinding) +- FAST: [Host directive template](https://www.fast.design/docs/fast-element/using-directives/#host-directives) +- Lit: [Nonexistent, but considered](https://github.com/lit/lit/issues/1825) + +## Detailed design + +The `` element is a synthetic element defined in a component's template HTML file. Similar to [dynamic components](https://github.com/salesforce/lwc-rfcs/pull/71), it does not actually render in the DOM. + +```html + +``` + +However, many attributes and directives that can be applied to a normal `HTMLElement` can be applied to ``. These include: + +- Standard [global HTML attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes), such as `class` and `tabindex` +- Custom HTML attributes, such as `data-*` +- Event listeners, such as `onclick` or `onfocus` +- The `lwc:spread` directive + +Other directives that apply to normal `HTMLElement`s, such as `lwc:inner-html`, `lwc:ref`, and `key`, are not supported. + +A bare `` with no attributes/listeners/directives is allowed, but effectively does nothing. + +### Restrictions + +#### Placement + +A `` element must be placed at the top level (root) of a `