diff --git a/text/0000-declarative-host.md b/text/0000-declarative-host.md new file mode 100644 index 00000000..39ac0fe8 --- /dev/null +++ b/text/0000-declarative-host.md @@ -0,0 +1,283 @@ +--- +title: Declarative host 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 host element + +## Summary + +Provides a declarative way to apply reactive attributes, classes, and event listeners to the host (root) 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 + +``` + +Instead, `` refers to either the shadow host element (in the case of shadow DOM components) or the root element (in the case of light DOM components). (In other words, if you are writing a component whose JavaScript file is `x/foo.js`, it refers to ``.) + +Many attributes and directives that can be applied to a normal `HTMLElement` can also 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 `