Here's the test case that I'm confused with. In html (in the end of body
):
<template id="test">
<test-tag class="test-id"></test-tag>
</template>
In the script:
class TestTag extends HTMLElement {
constructor() {
super();
console.log("TestTag created");
}
get Property() : string {
return "Hello";
}
}
// in some function:
customElements.define("test-tag", TestTag);
customElements.whenDefined("test-tag").then(() => {
console.log("test-tag defined");
var tag = document.createElement("test-tag") as TestTag;
console.log(tag.Property);
var template = document.getElementById("test") as HTMLTemplateElement;
var clone = template.content.cloneNode(true) as DocumentFragment;
var tag2 = clone.querySelector<TestTag>(".test-id");
if(tag2 == null){
console.error("tag2 is null");
} else {
//customElements.upgrade(tag2);
if(!(tag2 instanceof TestTag)){
console.error("WTF?!"); //did not expect to be here
}
console.log(tag2.Property); //tag2.Property is undefined
}
});
The first tag
object works as I expect. The second one doesn't: it seems that cloning the template creates a generic DOM element rather than an instance of my TestTag
class.
To me it seems to be the main function of custom elements - to define necessary behaviour and reuse it while still describing complex divs with HTML markup rather than some ugly construction code of dozens createElement
/appendChild
calls. So it seems like I'm missing something obvious. Like maybe shadow DOM mechanic but customElements.upgrade()
does nothing in this case.
My question is: if there's some well-known part of using custom elements I've missed then what is it; if not, what can be reasonably done to obtain a TestTag
instance as tag2
value in the example above and why my example behaves the way it does?
There is a difference between a Class Object and a DOM Element attached to the DOM
<template id="test">
<test-tag class="test-id"></test-tag>
</template>
<script>
class TestTag extends HTMLElement {
get Property() {
return "Hello";
}
}
customElements.define("test-tag", TestTag);
var tag = document.createElement("test-tag");
var template = document.getElementById("test");
var clone = template.content.cloneNode(true);
var tag2 = clone.querySelector(".test-id");
console.log(tag2.nodeName, tag2.constructor.name, tag2 instanceof HTMLElement, tag2 instanceof TestTag, tag2.Property);
document.body.append(tag2); // MAKE IT DOM!!!
console.log(tag2.nodeName, tag2.constructor.name, tag2 instanceof HTMLElement, tag2 instanceof TestTag, tag2.Property);
</script>