If we define a property like this on a color-span
custom element:
static get observedAttributes() {
return ['bgc'];
}
And get a reference to an instance like this while also changing the bgc property, should that cause the attributeChangedCallback
to fire?
const colorSpan = document.querySelector('color-span');
console.log(colorSpan);
colorSpan.bgc = 'BLUE';
I tried it in this demo, and it does not fire, so I just wanted to confirm my understanding that the attributeChangedCallback
will only fire when an attribute is set declaratively like this:
<color-span bgc="RED">Hello From Color Span</color-span>
colorSpan.bgc = 'BLUE';
will set the property, not the attribute. You can set the attribute programmatically using:
colorSpan.setAttribute('bgc', 'BLUE');
This will trigger the callback. However if you want to sync the property and the attribute you will have to implement that yourself.
class ColorSpanComponent extends HTMLElement {
static observedAttributes = ['bgc'];
constructor() {
super();
this._container = document.createElement('span');
this._container.append(document.createElement('slot'));
const shadowRoot = this.attachShadow({mode: 'closed'});
shadowRoot.append(this._container);
}
attributeChangedCallback(name, oldValue, newValue) {
switch (name) {
case 'bgc':
this._container.style.backgroundColor = newValue;
}
}
get bgc() {
return this._container.style.backgroundColor;
}
set bgc(value) {
if (this._container.style.backgroundColor !== value) {
this._container.style.backgroundColor = value;
this.setAttribute('bgc', value);
}
}
}
customElements.define('color-span', ColorSpanComponent);
const colorSpan = document.querySelector('color-span');
// log initial state
console.log(colorSpan.bgc, colorSpan.getAttribute('bgc'));
// change attribute and log
colorSpan.setAttribute('bgc', 'red');
console.log(colorSpan.bgc, colorSpan.getAttribute('bgc'));
// change property and log
colorSpan.bgc = 'blue';
console.log(colorSpan.bgc, colorSpan.getAttribute('bgc'));
<color-span bgc="green">TEST</color-span>