Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Web Components - attributeChangedCallback not firing

Im just starting out with web components and I cant seem to figure out why my attributeChangedCallback isnt firing;

I've been comparing it to a component ive created where everything is working as it should.

things I've checked:

  1. the spelling of the attr that is changing ("isOpen")
  2. the spelling of attributeChangedCallback (literally copied it from another component where it is working just to be sure),
  3. made sure its observedAttributes (plural) and the correct attr is set there,
  4. checked the setter and getter are working fine, and in the toggleStatus function I can log the isOpen attribute, and see it change as expected.

But if i try and do anything inside attributeChangedCallback ( example is just logging name) its not firing.

i am sure I'm missing something really simple??

class HamburgerMenu extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: "open" });
    this.shadowRoot.innerHTML = `
    <svg xmlns="http://www.w3.org/2000/svg" width="164" height="102" fill="none">
      <g stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="20">
        <path id="top" d="M10 92L154 92"/>
        <path id="middle" d="M10 50.8L154 50.8"/>
        <path id="bottom" d="M10 10L154 10"/>
      </g>
    </svg>`;
    this.svg = this.shadowRoot.querySelector("svg");
    this.svg.addEventListener("click", this.toggleStatus.bind(this));
  }

  static get observedAttributes() {
    return ["isOpen"];
  }

  attributeChangedCallback(name, oldValue, newValue) {
    console.log(name, oldValue, newValue);
  }

  get isOpen() {
    return this.getAttribute("isOpen");
  }

  set isOpen(val) {
    if (val) {
      this.setAttribute("isOpen", val);
    } else {
      this.removeAttribute("isOpen");
    }
  }

  toggleStatus() {
    this.setAttribute("isOpen", String(!eval(this.getAttribute("isOpen"))));
  }
}

if (!window.customElements.get("hamburger-menu")) {
  window.customElements.define("hamburger-menu", HamburgerMenu);
}
<hamburger-menu></hamburger-menu>
like image 703
Phl3bas Avatar asked Sep 13 '25 16:09

Phl3bas


1 Answers

  • Attributes must be lowercase, change "isOpen" to "isopen" and it will work
    see SO answer: are html5 data attributes case insensitive?

  • Your use of eval is creative; but there is a toggleAttribute method:
    see: https://developer.mozilla.org/en-US/docs/Web/API/Element/toggleAttribute

  • Your code runs because you only interact with the shadowRoot in the constructor.
    For other DOM related code you may have to wait till the connectedCallback (now not in your code) runs.
    For lifecycle see: https://andyogo.github.io/custom-element-reactions-diagram/

like image 137
Danny '365CSI' Engelman Avatar answered Sep 16 '25 05:09

Danny '365CSI' Engelman