If I use a custom element in HTML the provided attributes are all available in the constructor
<my-element myparam="fruit">I like bananas</my-element>
constructor() {}
super()
this.param = this.getAttribute("myparam")
> this.param = "fruit"
But if I create an instance of my custom element in JS with document.createElement
the constructor runs immediately, without the attributes being available.
const elem = document.createElement("my-element")
> this.param = null
Once I have appended the element to a DOM node I can hook attributeChangedCallback
which fires when I call elem.setAttribute
, to set this.param
. But that seems kind of ugly. I feel as though you ought not to have to create extra methods just to make a component usable via JS as well as HTML. It seems like there's similar situation with textNodes / Children too.
Is there any way to make attributes and children available to the constructor when creating nodes programmatically?
edit: So it seems seeking to do this is bad practice and I should only try to access attributes in the connectedCallback() function. As long as I use setAttribute before adding the component with .appendChild the values should be available a that point.
The constructor runs before the element has attached to the DOM when you use document.createElement
so you will not be able to access attributes as they don't exist yet.
You can access attributes in connectedCallback. The following basic example works
customElements.define(
"my-el",
class extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
this.foo = this.getAttribute("foo")
console.log("foo", this.foo) // logs "bar"
}
}
);
const el = document.createElement("my-el");
el.setAttribute("foo", "bar");
document.body.append(el)
You have some typos: my-element
vs. my-component
, this.getAttribute("myparam")
when you attribute above is called param
.