web components v1 intro

15
Web Components v1 intro

Upload: kenneth-rohde-christiansen

Post on 08-Feb-2017

145 views

Category:

Technology


0 download

TRANSCRIPT

Web Components v1 intro

Introduction

A mini intro to web components, starting from what you (presumable) already know and slowly adopting new vanilla web components features. After that, is shows how to accomplish the same using Polymer 2.0.

Intended to be instructor led.

<html><script>customElements.define('my-button', class extends HTMLElement { constructor() { super(); }

connectedCallback() { const textNode = document.createTextNode("Button"); const divEl = document.createElement("div"); divEl.style.backgroundColor = "lightblue"; divEl.appendChild(textNode); this.appendChild(divEl); }});</script>

<style> my-button { display: block; width: 50px; }</style>

<body> <my-button></my-button></body>

</html>

<html><script>customElements.define('my-button', class extends HTMLElement { constructor() { super(); const shadowRoot = this.attachShadow({ mode: 'open' });

const textNode = document.createTextNode("Button"); const divEl = document.createElement("div"); divEl.style.backgroundColor = "lightblue"; divEl.appendChild(textNode);

shadowRoot.appendChild(divEl); }});</script>

<style> my-button { display: block; width: 50px; }</style>

<body> <my-button></my-button></body>

</html>

<html><script>customElements.define('my-button', class extends HTMLElement { constructor() { super(); const shadowRoot = this.attachShadow({ mode: 'open' });

const textNode = document.createTextNode("Button"); const divEl = document.createElement("div"); divEl.style.backgroundColor = "lightblue"; divEl.appendChild(textNode);

shadowRoot.appendChild(divEl);

const styleEl = document.createElement("style"); styleEl.innerHTML = ` :host { display: block; } `; shadowRoot.appendChild(styleEl); }});</script>

<style> my-button { width: 50px; }</style>

<body> <my-button></my-button></body>

</html>

<html><script>customElements.define('my-button', class extends HTMLElement { constructor() { super(); const shadowRoot = this.attachShadow({ mode: 'open' });

const textNode = document.createTextNode("Button"); const divEl = document.createElement("div"); divEl.appendChild(textNode); shadowRoot.appendChild(divEl);

const styleEl = document.createElement("style"); styleEl.innerHTML = ` :host { display: block; } div { background-color: lightblue; } `; shadowRoot.appendChild(styleEl); }});

});</script>

<style> my-button { width: 50px; }</style>

<body> <my-button></my-button></body>

</html>

<html><script>customElements.define('my-button', class extends HTMLElement { constructor() { super(); const shadowRoot = this.attachShadow({ mode: 'open' });

const textNode = document.createTextNode("Button"); const divEl = document.createElement("div"); divEl.appendChild(textNode); shadowRoot.appendChild(divEl);

const styleEl = document.createElement("style"); styleEl.innerHTML = ` :host { display: block; } div { background-color: var(--button-color); } `; shadowRoot.appendChild(styleEl); }});

});</script>

<style> my-button { width: 50px; } #blue { --button-color: lightblue; } #green { --button-color: green; }</style>

<body> <my-button id="blue"></my-button> <my-button id="green"></my-button></body>

</html>

<html><template id="my-button-template"> <style> :host { display: block; } div { background-color: var(--button-color); } </style> <div>Button</div></template><script>customElements.define('my-button', class extends HTMLElement { constructor() { super(); const template = document.querySelector('#my-button-template'); const clone = document.importNode(template.content, true);

const shadowRoot = this.attachShadow({ mode: 'open' }); shadowRoot.appendChild(clone); }

});

});</script>

<style> my-button { width: 50px; } #blue { --button-color: lightblue; } #green { --button-color: green; }</style>

<body> <my-button id="blue"></my-button> <my-button id="green"></my-button></body>

</html>

<html><template id="my-button-template"> <style> :host { display: block; } div { background-color: var(--button-color); } </style> <div><slot></slot></div></template><script>customElements.define('my-button', class extends HTMLElement { constructor() { super(); const template = document.querySelector('#my-button-template'); const clone = document.importNode(template.content, true);

const shadowRoot = this.attachShadow({ mode: 'open' }); shadowRoot.appendChild(clone); }

});

});</script>

<style> my-button { width: 50px; } #blue { --button-color: lightblue; } #green { --button-color: green; }</style>

<body> <my-button id="blue">I'm blue</my-button> <my-button id="green">I'm green</my-button></body>

</html>

<html><template id="my-button-template"> <style> :host { display: block; } div { background-color: var(--button-color); } .uppercase { text-transform: uppercase; } </style> <div><slot></slot></div></template><style> my-button { width: 100px; } #blue { --button-color: lightblue; } #green { --button-color: green; }</style>

<body> <my-button id="blue" uppercase> I'm blue </my-button> <my-button id="green">I'm green</my-button></body>

<script>customElements.define('my-button', class extends HTMLElement { static get observedAttributes() { return ['uppercase']; }

constructor() { super(); const template = document.querySelector('#my-button-template'); const clone = document.importNode(template.content, true);

const shadowRoot = this.attachShadow({ mode: 'open' }); shadowRoot.appendChild(clone); }

attributeChangedCallback(name, oldValue, newValue) { // Allows for <my-button uppercase="[[ value ]]"> with Polymer, plus common behavior. this.uppercase = newValue === '' || newValue === 'true'; }

set uppercase(value) { const el = this.shadowRoot.querySelector("div"); if (value) { el.classList.add("uppercase"); } else { el.classList.remove("uppercase"); } }});</script>

</html>

<html><template id="my-button-template"> <style> :host { display: block; } div { background-color: var(--button-color); } .uppercase { text-transform: uppercase; } </style> <div><slot></slot></div></template><style> my-button { width: 100px; } #blue { --button-color: lightblue; } #green { --button-color: green; }</style>

<body> <my-button id="blue" uppercase> I'm blue </my-button> <my-button id="green">I'm green</my-button></body>

<script>customElements.define('my-button', class extends HTMLElement { static get observedAttributes() { return ['uppercase']; }

constructor() { ... }

attributeChangedCallback(name, oldValue, newValue) { this.uppercase = newValue === '' || newValue === 'true'; }

connectedCallback() { this.addEventListener('click', this._onClick.bind(this)); }

_onClick(ev) { // e.g. => Hi from I'M BLUE! alert(`Hi from ${this.innerText}!`); }

set uppercase(value) { const el = this.shadowRoot.querySelector("div"); if (value) { el.classList.add("uppercase"); } else { el.classList.remove("uppercase"); } }});</script>

</html>

<template id="my-button-template"> <style> ... </style> <div><slot></slot></div></template>...

<body> <script> (async () => { await customElements.whenDefined('my-button'); document.querySelector('#green').addEventListener('uppercasechange', ev => { console.log( `'${ev.target.innerText}' is ${!ev.detail.value ? 'not ' : ''}uppercase` ); }) })(); </script>

<my-button id="blue" uppercase> I'm blue </my-button> <my-button id="green">I'm green</my-button></body>

<script>customElements.define('my-button', class extends HTMLElement { ... constructor() { ... this._uppercase = false; } ...

_onClick(ev) { this.uppercase = !this.uppercase; const event = new CustomEvent("uppercasechange", { detail: { value: this._uppercase } }); this.dispatchEvent(event); }

attributeChangedCallback(name, oldValue, newValue) { this.uppercase = newValue === '' || newValue === 'true'; }

get uppercase() { return this._uppercase; }

set uppercase(value) { this._uppercase = Boolean(value); const el = this.shadowRoot.querySelector("div"); if (this._uppercase) { el.classList.add("uppercase"); } else { el.classList.remove("uppercase"); } }});</script>

<template id="my-button-template"> <style> ... </style> <div><slot></slot></div></template>...

<body> <script> function onUppercaseChange(ev) { console.log( `'${ev.target.innerText}' is ${!ev.detail.value ? 'not ' : ''}uppercase` ); }

(async () => { await customElements.whenDefined('my-button'); const greenEl = document.querySelector('#green'); greenEl.addEventListener('uppercasechange', onUppercaseChange); })();

</script> <my-button id="blue" uppercase on-uppercasechange="onUppercaseChange"> I'm Blue </my-button> <my-button id="green">I'm Green</my-button></body>

<script>customElements.define('my-button', class extends HTMLElement { ...

_onClick(ev) { this.uppercase = !this.uppercase; const event = new CustomEvent("uppercasechange", { detail: { value: this._uppercase } }); this.dispatchEvent(event);

// DO NOT DO THIS IN PRODUCTION const fn = this.getAttribute('on-uppercasechange'); if (window[fn] instanceof Function) { window[fn](event); } }

...});</script>

<head> <link rel="import" href="polymer/polymer-element.html"></head>

<dom-module id="my-button"> <template> <style> ... </style> <div id="container"><slot></slot></div> </template></dom-module>

<style> ...</style>

<body> <script> function onUppercaseChange(ev) { ... }

(async () => { await customElements.whenDefined('my-button'); const greenEl = document.querySelector('#green'); greenEl.addEventListener('uppercasechange', onUppercaseChange ); })();

</script> <my-button id="blue" uppercase> I'm Blue </my-button> <my-button id="green">I'm Green</my-button></body>

<script> class MyButton extends Polymer.Element { static get is() { return 'my-button'; } static get observedAttributes() { return ['uppercase']; } static get config() { return { properties: { uppercase: { type: Boolean } }, observers: [ 'uppercaseChanged(uppercase)' ] } }

attributeChangedCallback(name, oldValue, newValue) { if (name !== "uppercase") return; this.uppercase = newValue === '' || newValue === 'true'; }

connectedCallback() { super.connectedCallback(); this.addEventListener('click', _ => { this.uppercase = !this.uppercase; }); }

uppercaseChanged(newValue) { this.$.container.classList.toggle("uppercase", newValue); const event = new CustomEvent("uppercasechange", { detail: { value: newValue } }); this.dispatchEvent(event); } } customElements.define(MyButton.is, MyButton);</script>