Reputation: 413
I'm trying to create a polyfill of sorts using the Custom Elements API for custom elements used by an in-game browser engine to display buttons and similar. However, I can't seem to access the element's attributes (eg. src, href ...) from within the constructor.
Here is an example:
class KWButton extends HTMLElement {
constructor() {
super();
var attributes = this.attributes;
var shadow = this.attachShadow({
mode: 'open'
});
var img = document.createElement('img');
img.alt = this.getAttribute('text'); // the getAttribute call returns null
img.src = this.getAttribute('src'); // as does this one
img.width = this.getAttribute('width'); // and this
img.height = this.getAttribute('height'); // and this
img.className = 'vivacity-kwbutton'; // this works fine
shadow.appendChild(img);
img.addEventListener('click', () => {
window.location = this.getAttribute('href'); // this works perfectly fine
});
}
}
customElements.define('kw-button',
KWButton);
<kw-button src="https://placekitten.com/g/198/39" width="198" height="39" icon_src="https://placekitten.com/g/34/32" icon_width="34" icon_height="32" href="https://placekitten.com/" text="placekiten" color="#ffffff" size="18"></kw-button>
Upvotes: 9
Views: 4279
Reputation: 1776
Update as of 12me21 correction:
All in all I'd say now that since this is indeterminate to rely on this, well, exactly as it is warned by spec, I'd definitely refrain from accessing anything in the custom element c~tor, beside class' own definitions and alike.
Although I swear I've seen that spec once (the one @Supersharp mentioned), but nowadays:
getAttribute
is OKAYWell, probably we indeed should read that 'gain' as specifically referring to mutation.
One could say - wait, but if element can't gain any attribute - obviously there is nothing to inspect. Well, the following snippet works for me (on any browser):
class A extends HTMLElement {
constructor() {
super();
console.log(this.getAttribute('data-some'));
}
}
globalThis.customElements.define('x-a', A);
const e = document.createElement('x-a');
// console: null
const t = document.createElement('div');
t.innerHTML = '<x-a data-some="test"></x-a>';
// console: test
Upvotes: -1
Reputation: 31181
You cannot access the element DOM tree with querySelector()
and appendChild()
, and attributes with getAttribute()
and setAttribute()
in the constructor()
.
It's because at the time constructor()
is called the custom element has no content yet.
You should defer that in the connectedCallback()
method and it will be fine.
From the specs:
The element must not gain any attributes or children, as this violates the expectations of consumers who use the createElement or createElementNS methods.
In general, work should be deferred to connectedCallback as much as possible
Upvotes: 20