How to Get the Contents of a Custom Element
After some research online, I found the following nugget about connectedCallback
: each time the custom element is appended into a document-connected element. This will happen each time the node is moved, and may happen before the element's contents have been fully parsed.
Therefore, depending on the browser, innerHTML
may not in fact be defined when being used. That's why the above snippet, while fine in Firefox, doesn't work in Chrome or Edge.
To solve this problem, place the script
tags at the bottom of the body
, in which case the element will be parsed first, and the script will know what innerHTML
contains.
Another way around this is to wrap the custom element constructor inside a DOM loaded event. That event would look like so:
document.addEventListener('DOMContentLoaded', (e) => {
class markDown extends HTMLElement {
...
}
}
Yet another way of doing this is putting your script in a separate file, and marking the script
tag with the defer
attribute.
All three solutions work whether or not the class is explicitly named and defined by a separate statement, as mentioned by Triby's answer, or anonymous and wrapped by the custom element definition function, as in the original question.
I have been bitten by this so much, I purposely asked a StackOverflow question for people to find
wait for Element Upgrade in connectedCallback: FireFox and Chromium differences
The easiest workaround is a setTimeout
in the connectedCallback
<script>
customElements.define('my-element', class extends HTMLElement {
connectedCallback() {
console.log(this.innerHTML);// "A" in FireFox, "" in other Browsers
setTimeout(() => {
// now runs asap
console.log(this.innerHTML); // "A"
});
}
})
</script>
<my-element>A</my-element>
What this and all mentioned workarounds do is postpone code execution until the DOM is fully parsed.
setTimeout
runs after DOMContentLoaded
, but if you wrap everything in DOMContentLoaded
the whole Element creation runs late, same applies for defer
or placing <script>
at the end of your page
Supersharp explains the why better in:
wait for Element Upgrade in connectedCallback: FireFox and Chromium differences