For a Single Page Application I have registered some custom elements to the customElementRegistry which are rendered from string literals via insertAdjacentHTML(). Nesting these elements is no problem when done in html. But when I try to instantiate a parent custom element programmatically starting from customElements.get('entry-page') or document.createElement('div', {is: 'entry-page'}), the nested custom elements do not render as if not defined at all. Even customElements.whenDefined('nested-element').then(...) doesn't help.
function registerCustomElement(name, tpl) {
class cls extends HTMLDivElement {
connectedCallback() {
this.insertAdjacentHTML('afterbegin', tpl)
}
};
customElements.define(name, cls, {
extends: 'div'
})
}
let tpl1 = '<p class="box">inner HTML</p>'
let tpl2 = '<article class="outer">outer HTML<inner-html></inner-html></article>'
let tpl3 = '<article class="outer">revised outer HTML<div is="inner-html"></div></article>'
registerCustomElement('inner-html', tpl1)
registerCustomElement('outer-html', tpl2)
registerCustomElement('outer-html-revised', tpl3)
document.querySelector('main')
.insertAdjacentHTML('beforeend', '<div is="outer-html"></div>')
document.querySelector('main')
.insertAdjacentHTML('beforeend', '<div is="outer-html-revised"></div>')
body {
font-family: 'sans serif';
font-size: 0.8em
}
.box {
padding: 1em;
color: white;
background-color: olive;
}
.outer {
padding: 0.5em;
margin-bottom: 0.5em;
border: 2px solid darkorange
}
<h1>Embedded in html</h1>
<h2>version with 'inner-html' element</h2>
<outer-html></outer-html>
<h2>version with 'div is inner-html' element</h2>
<outer-html-revised></outer-html-revised>
<h1>Embedded programmatically</h1>
<main></main>
Each element is defined separately as a ES6 Module. I am currently not using shadow DOM.
Why a custom element does fully render including all nested elements when embedded in HTML, but not when implemented in the DOM programmatically?
Edit The behavior of the code snippet is different from Firefox 94.0. Whereas Firefox even nested custom elements with a custom tag name are evaluated, this is not the case with the code snippet engine. So, possibly, nested custom elements should better have the tag name of their anchestor and have an "is" attribute indicating the custom element name.
While in HTML the custom elements may be referenced by there names even in the string literals, the custom elements are based upon, this seems not to be true, when they are generated programmatically. In this case the spec requires something like <div is="custom-element-name">...