I’m putting a custom element in a template and then “selecting” it out to Window level. It seem to loose its identity as a custom element.
// In page
<template id="holder">
<my-element field="A"></my-element>
</template>
<script type="module">
class MyElement extends HTMLElement {
constructor() {
super();
}
get Field() { return this.getAttribute("field");}
}
window.customElements.define("my-element", MyElement);
</script>
<script>
const frag = document.querySelector("#holder").content;
const el = frag.querySelector("my-element");
console.log({el});
</script>
When <my-element>
is a page level and not in a template I can read xxx.Field
. When it comes from within a template it seems to no longer act like the custom element - xxx.Field isn’t defined. The script and selecting it and custom elements are both at “Window” level, so shouldn’t it “cast” correctly without having to be attached to document?
You can define a variable at window
that is a Promise
from whenDefined()
with value set to the custom element name, set the second script
type
to "module"
to handle the asynchronous code execution, within second <script type="module">
you can use then()
to get the custom element name, get the class
with customElements.get(<custom element name>)
, setPrototypeOf()
el
to the constructed custom element object, import the node into the current document
<template id="holder">
<my-element field="A"></my-element>
</template>
<script type="module">
const customElementName = "my-element";
class MyElement extends HTMLElement {
constructor() {
super();
}
get Field() { return this.getAttribute("field");}
}
window.customElements.define(customElementName, MyElement);
window.customElementPromise = window.customElements.whenDefined(customElementName)
.then(_ => customElementName);
</script>
<script type="module">
if (window.customElementPromise && window.customElementPromise instanceof Promise) {
window.customElementPromise
.then(customElementName => {
const frag = document.querySelector("#holder").content;
const el = frag.querySelector("my-element");
const CustomElement = window.customElements.get(customElementName);
Object.setPrototypeOf(el, new CustomElement);
document.importNode(el, true);
console.log(el.Field);
})
.catch(console.error);
} else {
console.assert("customElementName" in window, [window["customElementName"]])
}
</script>