2017-10-04 1 views
1

Je suis nouveau sur hyperHTML et j'expérimente avec. Voici ma question. Comment les gestionnaires d'événements sont-ils ajoutés pour les éléments de modèle répétés? Voici mon composant web:Gestionnaire d'événements sur un élément répété

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 };

Je veux ajouter un gestionnaire de clic dans l'onglet répétée et enregistrer tabSelected en tant que gestionnaire. Le gestionnaire de clic que j'ai ajouté renvoie une erreur de syntaxe Uncaught:

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

Répondre

1

Votre carte renvoie des chaînes simples, et que votre gestionnaire de clic ne pointe pas à une fonction, mais à une représentation de chaîne de votre fonction.

 ${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> 
     `)} 

Utilisez

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

à la place. CodePen

1

Il y a deux petits problèmes avec votre code:

  1. vous retournez juste une chaîne comme mentionné précédemment
  2. vous n'êtes pas obligatoire votre gestionnaire

Lorsque vous utilisez modèle littéraux il est facile d'oublier ce sont juste des ficelles. Vous devez renvoyer les nœuds DOM (ou fils) qui doivent toujours pointer sur le même onglet.

J'ai supposé tab.id sont uniques, et je les ai utilisés comme des identifiants liés au composant lui-même. Ceci est une meilleure version:

class IdxAdminTab extends HTMLElement { 
    constructor() { 
    super(); 
    this.selectedTab = this.selectedTab.bind(this); 
    this.render = hyper(this.attachShadow({mode: 'open'})); 
    this.updateView(); 
    } 

    selectedTab(e) { 
    console.log('tab selected'); 
    } 

    updateView() { 
    this.render` 
     <style>${css}</style> 
     <div id="tab-container"> 
     ${this.tabs.map(tab => hyper(this, `:${tab.id}`)` 
     <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>`; 
    } 

} 

Comme vous pouvez le voir, vous pouvez même utiliser {mode: 'closed'} tout en attribuant la shadowRoot une fois que la propriété rendu.

Vous avez maintenant un composant entièrement fonctionnel.

Cependant, hyperHTML est livré avec un assistant de Custom Elements appelé HyperHTMLElement, jetez un oeil à ses utilitaires, peut-être que cela va vous simplifier la vie.