Vanilla Web Components Inline Click Handler

Brandon Zhang - Jul 28 '22 - - Dev Community

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
. . . . . . . . . . . . .
Terabox Video Player