Skip to content

Instantly share code, notes, and snippets.

@marcus-at-localhost
Created June 1, 2023 05:33
Show Gist options
  • Save marcus-at-localhost/20678139ec26b224af31068ff874e0dd to your computer and use it in GitHub Desktop.
Save marcus-at-localhost/20678139ec26b224af31068ff874e0dd to your computer and use it in GitHub Desktop.
Web Components.md

All the ways to make a Web Component (native and Alpine.js) #webcomponents #alpinejs

https://webcomponents.dev/blog/all-the-ways-to-make-a-web-component/

const template = document.createElement('template');
template.innerHTML = `
  <style>
    * {
      font-size: 200%;
    }

    span {
      width: 4rem;
      display: inline-block;
      text-align: center;
    }

    button {
      width: 4rem;
      height: 4rem;
      border: none;
      border-radius: 10px;
      background-color: seagreen;
      color: white;
    }
  </style>
  <button id="dec">-</button>
  <span id="count"></span>
  <button id="inc">+</button>`;

class MyCounter extends HTMLElement {
  constructor() {
    super();
    this.count = 0;
    this.attachShadow({ mode: 'open' });
  }

  connectedCallback() {
    this.shadowRoot.appendChild(template.content.cloneNode(true));
    this.shadowRoot.getElementById('inc').onclick = () => this.inc();
    this.shadowRoot.getElementById('dec').onclick = () => this.dec();
    this.update(this.count);
  }

  inc() {
    this.update(++this.count);
  }

  dec() {
    this.update(--this.count);
  }

  update(count) {
    this.shadowRoot.getElementById('count').innerHTML = count;
  }
}

customElements.define('my-counter', MyCounter);
import Alpine from 'alpinejs'

const template = document.createElement("template");
template.innerHTML = `
  <style>
    span, button {
      font-size: 200%;
    }

    span {
      width: 4rem;
      display: inline-block;
      text-align: center;
    }

    button {
      width: 4rem;
      height: 4rem;
      border: none;
      border-radius: 10px;
      background-color: seagreen;
      color: white;
    }
  </style>
  <div x-data="$el.parentElement.data()">
    <button @click="dec()">-</button>
    <span x-text="count"></span>
    <button @click="inc()">+</button>
  </div>
`;

export class MyCounter extends HTMLElement {
  connectedCallback() {
    this.append(template.content.cloneNode(true));
  }

  data() {
    return {
      count: 0,
      inc() {
        this.count++;
      },
      dec() {
        this.count--;
      },
    };
  }
}

customElements.define("my-counter", MyCounter);
Alpine.start();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment