- From: Nicolas Gilbert <notifications@github.com>
- Date: Thu, 09 Mar 2023 05:45:38 -0800
- To: WICG/webcomponents <webcomponents@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <WICG/webcomponents/issues/989@github.com>
I would like to propose a new `extends` option that could be passed on `new CustomElementRegistry()`.
```js
const registry = new CustomElementRegistry({
extends: [registryA, registryB, registryC]
});
```
## Use case
As a developer, I am building a new component inside the `Products` page of my application. For this component, I will use components coming from the following scopes:
- Global components for the entire app
- Components only available to the `Products` section.
- Components coming from my company's own `Core` library.
- Components coming from 3rd party LibA and Lib2.
In turn, those component may use other component libraries.
Without registry extension, it may be quite a challenge to build a registry that define every dependencies correctly.
With registry extension, I would do:
```js
const registry = new CustomElementRegistry({
extends: [appRegistry, productsRegistry, coreRegistry, libARegistry, libBRegistry]
});
```
Conflicts between tag names (when 2 registries try to register the same name) would throw an error and would need to be handled manually.
## About scoped-constructor invocation
I believe that registry extension could be a good alternative to forbidding constructor on scoped elements, when combined with the restriction that constructor are registered on a single registry.
Extending a common registry would allow reuse of component without having to subclass over and over. The only cases where subclassing would be needed would be when registering some components on a different name than the default one. But this could be handle automatically and the new registry could be cached, see `getRegistry` helper in userland extensions below.
## Userland extensions
You could see some userland ways to make life even easier, here are a few ideas.
Good practice from libraries would be to export a `getRegistry` function with an optional prefix so conflicts could be avoided.
```js
import { getRegistry as getLibARegistry } from 'lib-a';
import { getRegistry as getLibBRegistry } from 'lib-b';
const registry = new CustomElementRegistry({
extends: [
// We register lib-a using predefined names
getLibARegistry(),
// As lib-b conflicts with lib-a, we use a custom prefix for those elements.
getLibBRegistry({ prefix: 'foobar' })
]
});
```
Libraries could build their own registries of multiple sub-registries, for when only part of the library is imported.
```js
const coreRegistry = new CustomElementRegistry({
extends: [
modalRegistry,
formRegistry,
gridRegistry,
titleRegistry,
/// Etc.
];
});
```
Component could include a `getRegistry` static prop that would return a registry with the component's dependencies. Combines nicely with the [requiredElements proposal](https://github.com/WICG/webcomponents/issues/988).
```js
// Could be improved with registry caching and automatic subclassing.
function getRegistry({ prefix = DEFAULT_PREFIX } = {}) {
const registry = new CustomElementRegistry({
extends: (this.requiredElements || []).map((Element) => Element.getRegistry({ prefix }))
});
registry.define(`${prefix}-${this.baseName}`, this);
return registry;
}
class ComponentA extends HTMLElement {
static baseName 'a'
static getRegistry = getRegistry;
}
class ComponentB extends HTMLElement {
static baseName 'b'
static requiredElements = [ComponentA];
static getRegistry = getRegistry;
connectedCallback() { this.appendChild(new ComponentA()); }
}
```
--
Reply to this email directly or view it on GitHub:
https://github.com/WICG/webcomponents/issues/989
You are receiving this because you are subscribed to this thread.
Message ID: <WICG/webcomponents/issues/989@github.com>
Received on Thursday, 9 March 2023 13:45:51 UTC