I'm trying to make somewhat of a reusable header for a website (multiple pages, can't be bothered to copy/paste everything); inside it I only have a logo-element
element (custom as well) whose id I want to make equal to the header's plus a __logo
suffix.
Here's the javascript:
class TopBar extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open" });
let logoElement = document.createElement("logo-element");
logoElement.setAttribute("id", `${ this.getAttribute("id") }__logo`);
this.shadowRoot.append(logoElement);
}
}
customElements.define('top-bar-element', TopBar);
And here's the HTML:
<top-bar-element id="top-bar"></top-bar-element>
Yet, when I check, I find <logo-element id="null__logo"></logo-element>
.
I suppose it is because the browser only sets the attribute after the creation of the element.
Is there any other explanation? Are there workarounds?
You are correct, in the constructor
phase the element is only in memory, can't access the DOM
So you have to do it in the connectedCallback
:
customElements.define('my-element', class extends HTMLElement {
constructor() {
let content = ["slot","logo-element"].map(x=>document.createElement(x));
super() // docs are wrong, super doesn't have to be first
.attachShadow({mode: "open" })
.append( ...content );
this.id = "TWO";
}
connectedCallback() {
this
.shadowRoot
.querySelector("logo-element")
.id = this.id + "__logo";
console.log(this.shadowRoot.innerHTML);
}
});
<my-element id="ONE">Hello World!</my-element>
But you do not need the constructor in your own element (the default one from HTMLElement
will be executed)
customElements.define('my-element', class extends HTMLElement {
connectedCallback() {
this.attachShadow({mode: "open"}).innerHTML = `<slot></slot>`;
let el = this.shadowRoot.appendChild(document.createElement("logo-element"));
el.id = this.id + "__logo";
console.log(this.shadowRoot.innerHTML);
let host = this.shadowRoot.getRootNode().host;
console.log(host==this , host);
}
});
<my-element id="TWO">Hello World!</my-element>
id
is a default attribute (like title and name) and (by default) have a Getter/Setterlogo-element
works, but still is an UNKNOWN Elementsuper()
is calledcustomElements.define('my-element', class extends HTMLElement {
connectedCallback() {
this.innerHTML = `<logo-element id="${this.id}__logo">${this.innerHTML}</logo-element>`;
console.log(this.innerHTML);
}
});
<my-element id="THREE">Hello World!</my-element>