Thursday, May 23, 2024
 Popular · Latest · Hot · Upcoming
28
rated 0 times [  34] [ 6]  / answers: 1 / hits: 8498  / 4 Years ago, thu, february 20, 2020, 12:00:00

In the following code, attributeChangedCallback never gets called even if the 'content' attribute is created, changed or removed.



class Square extends HTMLElement {

static get observedAttributes() {

return ['content'];
}
constructor(val) {
super();
console.log('inside constructor');
this.attachShadow({mode: 'open'});
this.shadowRoot.appendChild(document.createElement('button'));

this.button = this.shadowRoot.querySelector('button');
this.button.className = square;

this.content = val;

console.log('constructor ended');
}

get content() {
console.log('inside getter');
return this.button.getAttribute('content');
}
set content(val) {
console.log('setter being executed, val being: ', val);
// pass null to represent empty square
if (val !== null) {
this.button.setAttribute('content', val);

} else {
if (this.button.hasAttribute('content')) {
this.button.removeAttribute('content');
}
}

}
connectedCallback() {
//console.log('connected callback being executed now');
}

// not working :(
attributeChangedCallback(name, oldValue, newValue) {
console.log('attribute changed callback being executed now');
if (name === 'content') {
this.button.innerHTML = newValue?newValue: ;
}
}
}
customElements.define('square-box', Square);


Based on the best practices given here, I want the side-effect of attribute change (updation of innerHTML in my case) to take place in attributeChangedCallback. However when I move this updation to the setter, the code works fine.


More From » html

 Answers
2
set content(val) {
console.log('setter being executed, val being: ', val);
// pass null to represent empty square
if (val !== null) {
this.button.setAttribute('content', val);

} else {
if (this.button.hasAttribute('content')) {
this.button.removeAttribute('content');
}
}

}

You are mixing up parents & children


You are defining a setter on your Element <square-box> (►parent element)


When you do this.button.setAttribute('content', val);


You are changing a attribute of your <button> Element (►child element)


This will never trigger the attributeChangedCallback of (►parent) <square-box>

because its attributes were not changed


You either have to go "up the DOM" with .getRootNode() and/or .host to set attributes of parent elements.


or use Custom Events (bubbling up the DOM) to notify parents that children have done/changed something


I presume you meant to do


set content(val) {
// loose ==null comparison for null AND undefined,
// element.content=null; will remove the attribute
if (val==null)
this.removeAttribute('content');
else
// but you DO want .content(0) (0==false) set as "0"
this.setAttribute('content', val);
}

[#4695] Monday, February 17, 2020, 4 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
savanar

Total Points: 237
Total Questions: 105
Total Answers: 99

Location: Wales
Member since Mon, May 17, 2021
3 Years ago
savanar questions
;