Search code examples
hyperhtml

Event handler on repeated element


I'm new to hyperHTML and am experimenting with it. Here's my question. How are event handlers added for repeated template elements. Here's my web component:

import css from './component.css';
import isJson from '../utils/isJson.js';
const hyper = hyperHTML;

class IdxAdminTab extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({mode: 'open'});
  }

  attributeChangedCallback(name, oVal, nVal) {
    if (name === 'tabs' && isJson(nVal)) {
      this.tabs = JSON.parse(nVal);
      this.tabs.forEach((tab) => {
        tab.number = parseInt(tab.number, 10).toLocaleString();
      });
      this.updateView();
    }
  }

  clearSelections() {
    this.tabs.forEach((tab) => {
      tab.selected = false;
    });
  }

  connectedCallback() {
    this.updateView();
  }

  currentlySelected() {
    return this.tabs.find((tab) => tab.selected);
  }

  disconnectedCallback() {
    
  }

  tabSelected(evn) {
   
  }

  updateView() {
    hyper(this.shadowRoot)`
      <style>${css}</style>
      <div id="tab-container">
      ${this.tabs.map(tab => `
        <div class="${tab.selected ? 'selected' : ''}" id="${tab.id}" onclick="${this.selectedTab}">
          <div class="name">${tab.name}</div>
          <div class="number">${tab.number}</div>
        </div>
      `)}
      </div>
      `;
  }

  static get observedAttributes() {
    return ['tabs'];
  }
}

customElements.define('idx-admin-tab', IdxAdminTab);

export { IdxAdminTab };

I want to add a click handler in the repeated tab and register tabSelected as the handler. The click handler that I have added throws a Uncaught syntax error:

(function(event){[object HTMLElement]
})


Solution

  • Your map returns plain strings, and so your click handler does not point to a function, but to a string representation of your function.

          ${this.tabs.map(tab => `
            <div class="${tab.selected ? 'selected' : ''}" id="${tab.id}" onclick="${this.selectedTab}">
              <div class="name">${tab.name}</div>
              <div class="number">${tab.number}</div>
            </div>
          `)}
    

    Use

    hyperHTML.wire(tab)`<div>...</div>`  
    

    instead. CodePen