I try to get a html custom element to work:
When viewing the following example in the browser I must conclude that this.dataset.text attribute in the constructor() is:
- present before the script defining the custom element
- empty after the script defining the custom element
<html>
<head>
<title>myimage</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div>
before custom element definition: <my-element data-text="Replaced and works as expected">Not Replaced</my-element>
</div>
<script>
class MyElement extends HTMLElement {
constructor() {
super();
this.text_attribute= this.dataset.text;
}
connectedCallback() {
if (this.text_attribute) {
this.innerText = this.text_attribute;
}
}
}
customElements.define('my-element', MyElement);
</script>
<div>
after custom element definition: <my-element data-text="Replaced">Not Replaced</my-element>
</div>
</body>
</html>
This seems to be a common behavior in chrome and Firefox. I can provide some more facts:
- the
this.dataset.textis always present inconnectedCallback() - accessing the
text-attribut viathis.getAttribute('data-text')does behave in the same way as above
Can anyone explain the purpose of this seemingly buggy behavior?
CodePudding user response:
This isn't buggy behavior.
Your first <my-element> is processed by the DOM parser before you define it.
Thus all attributes are known (in the DOM) when the constructor executes.
In general you don't access DOM in the constructor; as it also runs when you do:
let foo = document.createElement("my-element"); // absolutly no DOM created
Here is a trimmed down example:
<style>
my-element { display:block }
</style>
<my-element id="FOO"> ONE </my-element>
<script>
customElements.define('my-element', class extends HTMLElement {
constructor() {
super();
document.body.append(` ► constructor id:${this.id} ◄ `);
}
connectedCallback() {
document.body.append(` ► connected id:${this.id} ◄ `);
}
});
</script>
<my-element id="BAR"> TWO </my-element>
<my-element id="BAZ"> THREE </my-element>
NOTE
How
FOOinnerHTML is written (because it was parsed) to the DOM before itsconstructorrunsHow
BARandBAZconstructor run before itsinnerHTMLis written to the DOM
and theidvalue doesn't exist yetI have seen many courses where they "save" you from this standard behavior by executing the
<script>async, thus after all DOM is parsed. They don't understand the technology...
