Skip to content

How do you recommend passing in data to a custom element

Gabriel Forti edited this page Jul 31, 2018 · 4 revisions

The way of passing data to html tags is by attributes. With custom elements you can pass in data in two ways

  1. Attributes
  2. Custom function

Attributes

A nice feature of custom elements is being able to watch for mutations on attributes.

Lets say we have score card.

function generateTemplate() {
    const template = document.createElement('template');
    template.innerHTML = `
        <style>
            :host h1 {
              font-size: 2.5rem;
              color: var(--on-surface, red);
            }
        </style>
        <article>
            <h1>ScoreCard</h1>                
        </article>
    `;
    return template;
}

class ScoreCard extends HTMLElement {

    constructor() {
      super();
      const shadowRoot = this.attachShadow({ mode: 'open' });
      shadowRoot.appendChild(generateTemplate().content.cloneNode(true));
      this.scoredisplay = this.shadowRoot.querySelector('h1')
    }

    connectedCallback() {
        this.render()
    }

    static get observedAttributes() {
      return ['data-score'];
    }

    attributeChangedCallback(attr, oldValue, newValue) {
        if ( oldValue !== newValue) {
            this.render()
        }
    }

    render() {
        this.scoredisplay.innerText = this.dataset.score
    }

}

window.customElements.define('score-card', ScoreCard)

We need the observedAttributes static function to return an array of attributes to observe. If it is not on the list the attribute will be not observed.

The attributeChangedCallback function will be called every time the attribute changes. The render function is a custom function, not part of the custom elements interface.

In the html we can use the custom element like so

<score-card data-score="0"></score-card>

Update it in JavaScript like so

setInterval(()=>{
    document.querySelector('score-card').dataset.score = Math.floor(Math.random() * 100) +1
}, 1000)

If you wanted to create getter/setter or use non data attributes you can!

<score-card score="0"></score-card>
setInterval(()=>{
    document.querySelector('score-card').score = Math.floor(Math.random() * 100) +1
}, 1000)
static get observedAttributes() {
   return ['score'];
}

render() {
    this.scoredisplay.innerText = this.score
}

get score() {
    return this.getAttribute('score');
}
set score(newValue) {
    this.setAttribute('score', newValue);
}

Custom Function

The idea is you would pass the data into a function and have it render. If you are doing this and not using attributes you lose the benefit of mutation listeners.

Do not use custom elements to manage data, use a service. Custom elements are just to display data.

Clone this wiki locally