javascript - attributeChangedCallback doesn't get called even after defining observedAttributes - Stack Overflow

In the following code, attributeChangedCallback never gets called even if the 'content' attri

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.

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.

Share Improve this question asked Feb 20, 2020 at 11:59 user103643user103643 431 gold badge1 silver badge3 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 4
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 parison 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);
    }

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744304063a4567644.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信