> whoami
<ncr-payment-portal> <ncr-form> <ncr-formfield type="text"></ncr-formfield> <ncr-formfield type="email"></ncr-formfield> ... </ncr-form> <ncr-pay-btn></ncr-pay-btn> </ncr-payment-portal>
<an-incdec>
class IncDec extends HTMLElement { constructor() { super(); const dummyEl = document.createElement('div'); dummyEl.innerHTML = 'hello'; this.appendChild(dummyEl); } connectedCallback() { } } customElements.define('an-incdec', IncDec);
You can now use
<an-incdec> in your
HTML and it will render 'hello'
<template id="incdec-template"> <style> :host { display: flex; margin: 50px; } button { width: 100px; font-size: 4rem; background: #6fbfed; border-radius: 20px; } span { width: 100px; padding: 20px; } </style> <button id="dec"> - </button> <span id="count"> 0 </span> <button id="inc"> + </button> </template>
Don't worry about what
:host means just yet. It
will make more sense when we talk about the Shadow
DOM
class IncDec extends HTMLElement { constructor() { super(); const template = document.getElementById("incdec-template"); const el = template.content.cloneNode(true); this.appendChild(el); } connectedCallback() { } } customElements.define('an-incdec', IncDec);
The code will render the UI fine, but the styles
will leak out because we are not using the Shadow
DOM. Let's fix that!
class IncDec extends HTMLElement { constructor() { super(); this.attachShadow({mode: 'open'}); const template = document.getElementById("#incdec-template"); const el = template.content.cloneNode(true); this.shadowRoot.append(el); this._count = 0; } get count() { return this._count; } set count(val) { if (val < 0) { alert("cannot go less than zero"); return; } this._count = val; this.shadowRoot.querySelector("#count").innerHTML = this.count; } connectedCallback() { this.count = 0; this.shadowRoot.querySelector("#dec").addEventListener("click", () => { this.count -= 1; }); this.shadowRoot.querySelector("#inc").addEventListener("click", () => { this.count += 1; }); } } customElements.define('an-incdec', IncDec);
Whatever styles you set in the
<style> is scoped to
just your component. It
WILL NOT leak
out
import { html, define } from 'hybrids'; export function inc(host) { host.count += 1; } export function dec(host) { host.count -= 1; } export const IncDec = { count: 0, render: ({ count }) => html` <button onclick="${dec}"> - </button> <span>${count}</span> <button onclick="${inc}"> + </button> `, } define('an-incdec', IncDec);
import React from "react"; class App extends React.Component { ... render() { return ( <div> A cool web component! <an-indec></an-indec> </div> ); } }
No! Web Components are compatible with every framework.
In the above example, we are using our component in
React.