skip to Main Content

I’m new in JavaScript web components and for this case I was trying to call a method by clicking on button but it doesn’t work…

Run this code:

<test-element></test-element>


  <script type="text/javascript">
    class TestElement extends HTMLElement {
      constructor() {
        super();
      }
      sayHello() {
        alert('Hello')
      }
      connectedCallback() {
        this.innerHTML = `<button onclick="${this.sayHello}">Hello</button>`;
      }
    }
    customElements.define('test-element', TestElement);
  </script>

if you click on Hello it doesn’t execute sayHello method…

2

Answers


  1. The issue here is that this context within the onclick attribute of the button does not refer to the instance of the TestElement class. To make it work, you should add an event listener for the button click inside the connectedCallback method.

    <test-element></test-element>
    
    <script type="text/javascript">
      class TestElement extends HTMLElement {
        constructor() {
          super();
        }
        sayHello() {
          alert('Hello');
        }
        connectedCallback() {
        this.innerHTML = `<button class="helloButton">Hello</button>`;
        const button = this.querySelector(".helloButton");
          button.addEventListener("click", () => {
            this.sayHello();
          });
        }
      }
      customElements.define('test-element', TestElement);
    </script>
    
    Login or Signup to reply.
  2. As said in the other correct answer, the scope is wrong.

    In Web Components with shadowDOM you can use onclick="this.getRootNode()"

    Alternative is to not use an inline eventHandler and attach a click handler yourself.
    Which, if you know no-one else needs to attach handlers,
    does not require addEventListener (which allows for multiple handlers on one element)

    Add a Helper function element to build your DOM and it becomes:

    <test-element></test-element>
    
    
    <script>
      customElements.define('test-element', class extends HTMLElement {
        connectedCallback() {
          const element = (tag, props = {}) => Object.assign(document.createElement(tag), props);
          this.counter = 0;
          this.append(
            element("BUTTON", {
              innerHTML: "My Button",
              onclick: (evt) => {
                this.span.innerHTML = ++this.counter;
                this.sayHello();
              }
            }),
            this.span = element("SPAN", {
              innerHTML: this.counter,
            })
          )
        }
        sayHello() {
          console.log('Counted' , this.counter);
        }
      });
    </script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search