107 lines
3.6 KiB
Markdown
107 lines
3.6 KiB
Markdown
# Principles >> Scoped Elements ||40
|
|
|
|
The [CustomElementRegistry](https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry) provides methods for registering custom elements. One of the limitations of working with this global registry is that multiple versions of the same element cannot co-exist. This causes bottlenecks in software delivery that should be managed by the teams and complex build systems. [Scoped Custom Element Registries](https://github.com/w3c/webcomponents/issues/716) is a proposal that will solve the problem. Since this functionality won't be available (especially not cross browser) anytime soon, we've adopted [OpenWC's Scoped Elements](https://open-wc.org/docs/development/scoped-elements/).
|
|
|
|
Whenever a lion component uses composition (meaning it uses another lion component inside), we
|
|
apply ScopedElementsMixin to make sure it uses the right version of this internal component.
|
|
|
|
```js
|
|
import { LitElement, html } from '@lion/ui/core.js';
|
|
import { ScopedElementsMixin } from '@open-wc/scoped-elements/lit-element.js';
|
|
import { html, LitElement } from 'lit';
|
|
|
|
import { LionInput } from '@lion/ui/input.js';
|
|
import { LionButton } from '@lion/ui/button.js';
|
|
|
|
class MyElement extends ScopedElementsMixin(LitElement) {
|
|
static get scopedElements() {
|
|
return {
|
|
'lion-input': LionInput,
|
|
'lion-button': LionButton,
|
|
};
|
|
}
|
|
|
|
render() {
|
|
return html`
|
|
<lion-input label="Greeting" name="greeting" .modelValue=${'Hello world'}></lion-input>
|
|
<lion-button>Save</lion-button>
|
|
`;
|
|
}
|
|
}
|
|
```
|
|
|
|
## Polyfill
|
|
|
|
This package requires use of the Scoped Custom Element Registry polyfill. Make sure to load it as the first thing in your application:
|
|
|
|
```js
|
|
import '@webcomponents/scoped-custom-element-registry';
|
|
```
|
|
|
|
If you're using `@web/rollup-plugin-polyfills-loader`, you can use it in your rollup config like this:
|
|
|
|
```js
|
|
polyfillsLoader({
|
|
polyfills: {
|
|
scopedCustomElementRegistry: true,
|
|
},
|
|
});
|
|
```
|
|
|
|
If you're using `@web/dev-server` for local development, you can use the `@web/dev-server-polyfill` plugin:
|
|
|
|
```js
|
|
polyfill({
|
|
scopedCustomElementRegistry: true,
|
|
});
|
|
```
|
|
|
|
## Edge cases
|
|
|
|
Sometimes we need to render parts of a template to light dom for [accessibility](https://wicg.github.io/aom/explainer.html). For instance we render a node via `lit-html` that we append to the host element, so it gets slotted in the right position.
|
|
In this case, we should also make sure that we also scope the rendered element.
|
|
|
|
We can do this as follows:
|
|
|
|
```js
|
|
_myLightTemplate() {
|
|
return html`
|
|
This template may be overridden by a Subclasser.
|
|
Even I don't end up in shadow root, I need to be scoped to constructor.scopedElements as well.
|
|
<div>
|
|
<lion-button>True</lion-button>
|
|
<lion-input label="xyz"></lion-input>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
__getLightDomNode() {
|
|
const renderParent = document.createElement('div');
|
|
this.constructor.render(this._myLightTemplate(), renderParent, {
|
|
scopeName: this.localName,
|
|
eventContext: this,
|
|
});
|
|
// this node will be appended to the host
|
|
return renderParent.firstElementChild;
|
|
}
|
|
|
|
connectedCallback() {
|
|
super.connectedCallback();
|
|
this.appendChild(this.__getLightDomNode());
|
|
}
|
|
```
|
|
|
|
In a less complex case, we might just want to add a child node to the dom.
|
|
|
|
```js
|
|
import { LitElement } from 'lit';
|
|
import { ScopedElementsMixin } from '@open-wc/scoped-elements/lit-element.js';
|
|
|
|
...
|
|
|
|
__getLightDomNode() {
|
|
return document.createElement('lion-input', this.constructor.scopedElements);
|
|
}
|
|
```
|
|
|
|
We encourage you to have a look at [OpenWC's Scoped elements](https://open-wc.org/docs/development/scoped-elements/).
|