SlideShare uma empresa Scribd logo
1 de 15
Baixar para ler offline
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>
Web components v1 intro

Mais conteúdo relacionado

Mais procurados

WordPressのテンプレートをカスタマイズするために必要なphpを初歩から解説
WordPressのテンプレートをカスタマイズするために必要なphpを初歩から解説WordPressのテンプレートをカスタマイズするために必要なphpを初歩から解説
WordPressのテンプレートをカスタマイズするために必要なphpを初歩から解説Takashi Uemura
 
Peek inside the fantastical Ukrainian Village home and studio of artists Jare...
Peek inside the fantastical Ukrainian Village home and studio of artists Jare...Peek inside the fantastical Ukrainian Village home and studio of artists Jare...
Peek inside the fantastical Ukrainian Village home and studio of artists Jare...irwinvifxcfesre
 
2016 06-11 Дмитрий Алексеенков. Android Data Binding
2016 06-11 Дмитрий Алексеенков. Android Data Binding2016 06-11 Дмитрий Алексеенков. Android Data Binding
2016 06-11 Дмитрий Алексеенков. Android Data BindingОмские ИТ-субботники
 
Un juego creado en php
Un juego creado en phpUn juego creado en php
Un juego creado en phpErwin Lobo
 
Crud secara simultan ala php myadmin
Crud secara simultan ala php myadminCrud secara simultan ala php myadmin
Crud secara simultan ala php myadminRizal Di Caprio
 
Simple flat ui css accordion
Simple flat ui css accordionSimple flat ui css accordion
Simple flat ui css accordionSamsury Blog
 
J query aula01
J query aula01J query aula01
J query aula01Suissa
 
[2019] 실용적인 프런트엔드 테스트 전략
[2019] 실용적인 프런트엔드 테스트 전략[2019] 실용적인 프런트엔드 테스트 전략
[2019] 실용적인 프런트엔드 테스트 전략NHN FORWARD
 
Intro to jQuery UI
Intro to jQuery UIIntro to jQuery UI
Intro to jQuery UIappendTo
 
jQuery sans jQuery
jQuery sans jQueryjQuery sans jQuery
jQuery sans jQuerygoldoraf
 
Юнит тестирование в Zend Framework 2.0
Юнит тестирование в Zend Framework 2.0Юнит тестирование в Zend Framework 2.0
Юнит тестирование в Zend Framework 2.0zfconfua
 
Javascript and jQuery for Mobile
Javascript and jQuery for MobileJavascript and jQuery for Mobile
Javascript and jQuery for MobileIvano Malavolta
 
New text document (2) 2
New text document (2) 2New text document (2) 2
New text document (2) 2raj lex
 
Introducción WebComponents y Visual Studio
Introducción WebComponents y Visual StudioIntroducción WebComponents y Visual Studio
Introducción WebComponents y Visual StudioDavid Chavarri
 
Php codigos interfaces fredy guzman cusihunca
Php codigos interfaces   fredy guzman cusihuncaPhp codigos interfaces   fredy guzman cusihunca
Php codigos interfaces fredy guzman cusihuncaTigger_Fred
 

Mais procurados (19)

Sis quiz
Sis quizSis quiz
Sis quiz
 
jQuery入門
jQuery入門jQuery入門
jQuery入門
 
WordPressのテンプレートをカスタマイズするために必要なphpを初歩から解説
WordPressのテンプレートをカスタマイズするために必要なphpを初歩から解説WordPressのテンプレートをカスタマイズするために必要なphpを初歩から解説
WordPressのテンプレートをカスタマイズするために必要なphpを初歩から解説
 
Peek inside the fantastical Ukrainian Village home and studio of artists Jare...
Peek inside the fantastical Ukrainian Village home and studio of artists Jare...Peek inside the fantastical Ukrainian Village home and studio of artists Jare...
Peek inside the fantastical Ukrainian Village home and studio of artists Jare...
 
2016 06-11 Дмитрий Алексеенков. Android Data Binding
2016 06-11 Дмитрий Алексеенков. Android Data Binding2016 06-11 Дмитрий Алексеенков. Android Data Binding
2016 06-11 Дмитрий Алексеенков. Android Data Binding
 
Un juego creado en php
Un juego creado en phpUn juego creado en php
Un juego creado en php
 
Crud secara simultan ala php myadmin
Crud secara simultan ala php myadminCrud secara simultan ala php myadmin
Crud secara simultan ala php myadmin
 
Simple flat ui css accordion
Simple flat ui css accordionSimple flat ui css accordion
Simple flat ui css accordion
 
J query aula01
J query aula01J query aula01
J query aula01
 
[2019] 실용적인 프런트엔드 테스트 전략
[2019] 실용적인 프런트엔드 테스트 전략[2019] 실용적인 프런트엔드 테스트 전략
[2019] 실용적인 프런트엔드 테스트 전략
 
Intro to jQuery UI
Intro to jQuery UIIntro to jQuery UI
Intro to jQuery UI
 
jQuery sans jQuery
jQuery sans jQueryjQuery sans jQuery
jQuery sans jQuery
 
Юнит тестирование в Zend Framework 2.0
Юнит тестирование в Zend Framework 2.0Юнит тестирование в Zend Framework 2.0
Юнит тестирование в Zend Framework 2.0
 
DOCUMENTACION PAGINA WEB PHP
DOCUMENTACION PAGINA WEB PHPDOCUMENTACION PAGINA WEB PHP
DOCUMENTACION PAGINA WEB PHP
 
Javascript and jQuery for Mobile
Javascript and jQuery for MobileJavascript and jQuery for Mobile
Javascript and jQuery for Mobile
 
New text document (2) 2
New text document (2) 2New text document (2) 2
New text document (2) 2
 
Jquery Framework
Jquery FrameworkJquery Framework
Jquery Framework
 
Introducción WebComponents y Visual Studio
Introducción WebComponents y Visual StudioIntroducción WebComponents y Visual Studio
Introducción WebComponents y Visual Studio
 
Php codigos interfaces fredy guzman cusihunca
Php codigos interfaces   fredy guzman cusihuncaPhp codigos interfaces   fredy guzman cusihunca
Php codigos interfaces fredy guzman cusihunca
 

Mais de Kenneth Rohde Christiansen

Mais de Kenneth Rohde Christiansen (10)

Progressive Web Apps - deep dive
Progressive Web Apps - deep diveProgressive Web Apps - deep dive
Progressive Web Apps - deep dive
 
New trends on web platform
New trends on web platformNew trends on web platform
New trends on web platform
 
Web Assembly (W3C TPAC presentation)
Web Assembly (W3C TPAC presentation)Web Assembly (W3C TPAC presentation)
Web Assembly (W3C TPAC presentation)
 
Generic sensors for the Web
Generic sensors for the WebGeneric sensors for the Web
Generic sensors for the Web
 
HTML literals, the JSX of the platform
HTML literals, the JSX of the platformHTML literals, the JSX of the platform
HTML literals, the JSX of the platform
 
Cold front - bridging the web and the physical world
Cold front - bridging the web and the physical worldCold front - bridging the web and the physical world
Cold front - bridging the web and the physical world
 
WebKit, why it matters (PDF version)
WebKit, why it matters (PDF version)WebKit, why it matters (PDF version)
WebKit, why it matters (PDF version)
 
WebKit, why it matters?
WebKit, why it matters?WebKit, why it matters?
WebKit, why it matters?
 
Qt WebKit going Mobile
Qt WebKit going MobileQt WebKit going Mobile
Qt WebKit going Mobile
 
Connecting Technology for Great Experiences - How does QML and Web fit together?
Connecting Technology for Great Experiences - How does QML and Web fit together?Connecting Technology for Great Experiences - How does QML and Web fit together?
Connecting Technology for Great Experiences - How does QML and Web fit together?
 

Web components v1 intro

  • 2. 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.
  • 3. <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>
  • 4. <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>
  • 5. <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>
  • 6. <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>
  • 7. <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>
  • 8. <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>
  • 9. <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>
  • 10. <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>
  • 11. <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>
  • 12. <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>
  • 13. <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>
  • 14. <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>