CHAPTER 2. Making Components

Basics

A First Example

chapter2/time/time.js
class TimeFormatted extends HTMLElement {

  connectedCallback() {
    let date = new Date(this.getAttribute('datetime') || Date.now());

    this.innerHTML = new Intl.DateTimeFormat("default", {
      year: this.getAttribute('year') || undefined,
      month: this.getAttribute('month') || undefined,
      day: this.getAttribute('day') || undefined,
      hour: this.getAttribute('hour') || undefined,
      minute: this.getAttribute('minute') || undefined,
      second: this.getAttribute('second') || undefined,
      timeZoneName: this.getAttribute('time-zone-name') || undefined,
    }).format(date);
  }

}

customElements.define("time-formatted", TimeFormatted);
chapter2/time/index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Time Formatted</title>
    <script src="time.js"></script>
  </head>
  <body>
    <time-formatted
      datetime="2020-04-13"
      year="numeric"
      month="long"
      day="numeric"
      hour="numeric"
      minute="numeric"
      second="numeric"
      time-zone-name="short"
    ></time-formatted>
  </body>
</html>

Observing Attributes

chapter2/observed/time.js

class TimeFormat extends HTMLElement {

  render() { // (1)
    let date = new Date(this.getAttribute('datetime') || Date.now());

    this.innerHTML = new Intl.DateTimeFormat("default", {
      year: this.getAttribute('year') || undefined,
      month: this.getAttribute('month') || undefined,
      day: this.getAttribute('day') || undefined,
      hour: this.getAttribute('hour') || undefined,
      minute: this.getAttribute('minute') || undefined,
      second: this.getAttribute('second') || undefined,
      timeZoneName: this.getAttribute('time-zone-name') || undefined,
    }).format(date);
  }

  connectedCallback() { // (2)
    if (!this.rendered) {
      this.render();
      this.rendered = true;
    }
  }

  static get observedAttributes() { // (3)
    return ['datetime', 'year', 'month', 'day', 'hour', 'minute', 'second', 'time-zone-name'];
  }

  attributeChangedCallback(name, oldValue, newValue) { // (4)
    this.render();
  }

}

customElements.define("time-format", TimeFormat);
chapter2/observed/index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Time Formatted</title>
    <script src="time.js"></script>
  </head>
  <body>
    <time-format
      datetime="2020-04-13"
      year="numeric"
      month="long"
      day="numeric"
      hour="numeric"
      minute="numeric"
      second="numeric"
      time-zone-name="short"
    ></time-format>
    <script>
      const elem = document.querySelector('time-format');
      setInterval(() => elem.setAttribute('datetime', new Date()), 1000);
    </script>
  </body>
</html>