Search code examples
javascriptweb-component

Javascript Web-Components - Add function to the shadow-DOM


I'm working on new web-components for my site, which work fine just with html/css. However, I was not able to add some kind of javascript functionality to my shadow DOM.

In my case, it's about a button inside the component, which should trigger a function handling the event. Nevertheless, I always get an error that the function is not defined. I know that the shadow DOM should protect the inside but I do not know how to implement my js properly. Hopefully you can help :)

class InfoSmall extends HTMLElement {
// attributes
constructor() {
  super();
  // not important
}

// component attributes
static get observedAttributes() {
  return [''];
}

// attribute change
attributeChangedCallback(property, oldValue, newValue) {
  if (oldValue == newValue) return;
  this[ property ] = newValue;
};

connectedCallback() {
  const shadow = this.attachShadow({ mode: 'open' });

  shadow.innerHTML = `
  <div class="container>
     <button id="copy"></button>
  </div>`

  shadow.querySelector('#copy').addEventListener("click", function () {
    // functionality
  });
}
}

I also tried the onclick-attribute but it was the same for me: no function defined. Or I also tried writing the script inside the innerHTML with an HTML-tag...


Solution

  • You are creating invalid HTML because you are missing a double quote on class="container>

    Your code can be condensed to:

    <script>
      customElements.define("my-element", class extends HTMLElement {
        constructor() {
          super() // sets AND returns 'this' scope
            .attachShadow({mode: 'open'}) // sets AND returns this.shadowRoot
            .innerHTML = `<div class="container">
                            <button>Click Me!</button>
                          </div>`;
          this.shadowRoot
              .querySelector('button')
              .onclick = () => {
                                 alert("YEAH!")
                               };
        }
      });
    </script>
    
    <my-element></my-element>