Consider this HTML template
with two flat x-element
s and one nested.
<template id="fooTemplate">
<x-element>Enter your text node here.</x-element>
<x-element>
<x-element>Hello, World?</x-element>
</x-element>
</template>
How to initialise (fire constructor) all custom elements in cloned from fooTemplate
document fragment without appending it to DOM, neither by extending built-in elements with is="x-element"
; either entire fragment.
class XElement extends HTMLElement {
constructor() { super(); }
foo() { console.log( this ); }
} customElements.define( 'x-element', XElement );
const uselessf = function( temp ) {
const frag = window[ temp ].content.cloneNode( true );
/* Your magic code goes here:
*/ do_black_magic( frag );
for (const e of frag.querySelectorAll('x-element') )
e.foo(); // This should work.
return frag;
};
window['someNode'].appendChild( uselessf('fooTemplate') );
Note that script executes with defer
attribute.
We can initialise template with this arrow function:
const initTemplate = temp =>
document.createRange().createContextualFragment( temp.innerHTML );
const frag = initTemplate( window['someTemplate'] );
Or with this method defined on template
prototype (I prefer this way):
Object.defineProperty(HTMLTemplateElement.prototype, 'initialise', {
enumerable: false,
value() {
return document.createRange().createContextualFragment( this.innerHTML );
}
});
const frag = window['someTemplate'].initialise();
In any case in result this code will work fine:
for (const elem of frag.querySelectorAll('x-element') )
elem.foo();
window['someNode'].appendChild( frag );
I'm not sure if these methods are the most effective way to initialise custom elements in template.
Also note that there is no need for cloning template.