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.
Advertisement
Answer
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.