DEV Community

Brandon Zhang
Brandon Zhang

Posted on

Vanilla Web Components Inline Click Handler

When we're setting up inline click handlers inside vanilla web components, this below refers to h1 element.

export default class wc_parent extends HTMLElement {
  constructor() {
    super()
    this.attachShadow({mode: 'open'})
  }

  render() {
    const template = document.createElement('template')
    template.innerHTML = `
      <h1 onclick="this.handle_click(event)">hello</h1>
      <style>
        :host {
          display: block;
        }
      </style>
    `

    this.shadowRoot.appendChild(
      template.content.cloneNode(true)
    )
  }

  handle_click(e) {
    console.log(e)
  }

  connectedCallback() {
    this.render()
  }
}
Enter fullscreen mode Exit fullscreen mode

If we want to handle inline click, we'll need to make it work like this, inside connectedCallback():

connectedCallback() {
  this.shadowRoot.addEventListener('click', this.handle_click)
}
Enter fullscreen mode Exit fullscreen mode

Life will be a bit easier if we can make this inside onclick="this.handle_click(event)" points to the component instead of window object, like React. I was thinking adding a property on window and points to this component window[this.localName] = this, and then replace this to window[this.localName] inside render() method.

export default class wc_parent extends HTMLElement {
  constructor() {
    super()
    this.attachShadow({mode: 'open'})
    window[this.localName] = this 
  }

  render() {
    const template = document.createElement('template')
    template.innerHTML = `
      <h1 onclick="this.handle_click(event)">hello</h1>
      <style>
        :host {
          display: block;
        }
      </style>
    `
    // replace this to window['wc-parent']
    template.innerHTML = template.innerHTML.replace(
      /this/g, 
      `window['${this.localName}']`
    )

    this.shadowRoot.appendChild(
      template.content.cloneNode(true)
    )
  }

  handle_click(e) {
    console.log(e)
  }

  connectedCallback() {
    this.render()
  }
}
Enter fullscreen mode Exit fullscreen mode

Now this is how it displays in front end if we inspect the HTML elements. This part onclick="window['wc-parent'].handle_click(event)" makes sense to me as it clearly indicate that we can find this method inside wc-parent component.

<wc-parent>
  #shadow-root (open)
    <h1 onclick="window['wc-parent'].handle_click(event)">hello</h1>
</wc-parent>

Enter fullscreen mode Exit fullscreen mode

Top comments (0)