Slide 1

Slide 1 text

+Eric Bidelman @ebidel Using ES6 with Polymer Amsterdam

Slide 2

Slide 2 text

+Eric Bidelman @ebidel Using ES6 with Polymer Amsterdam ES2015

Slide 3

Slide 3 text

@ebidel github.com/ebidel

Slide 4

Slide 4 text

@ebidel @polymer #polymersummit On deck agenda ‣Intro to small ES6 features ‣Defining Polymer elements using classes

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

e.path content.getDistributedNodes(); document.registerElement(‘custom-element’); :host { display: block; } ::content > * { color: blue; } el.createShadowRoot(); el.shadowRoot :unresolved { opacity: 0; }

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

behaviors: [SwipBehavior] on-tap=“_handleTap” Polymer({is:‘my-element’}); :host { } .warning { color: var( }
{{fooBar}} observers: [ ‘_update(one, two, thre ] Polymer.Base.importHref()

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

Object.is(future, true)

Slide 11

Slide 11 text

= natural fit +

Slide 12

Slide 12 text

kangax.github.io/compat-table/es6/

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

@ebidel @polymer #polymersummit Don’t forget all the stuff ES6 brings a lot of new features

Slide 15

Slide 15 text

@ebidel @polymer #polymersummit Don’t forget all the stuff ES6 brings a lot of new features ‣ let ‣ Spread operator ‣ Default & Rest params ‣ => ‣ new Proxy() ‣ Classes ‣ new Promise() ‣ Object literal shorthand ‣ Template strings ‣ const ‣ Iterators, Generators ‣ Symbols ‣ String/Array methods ‣ Modules

Slide 16

Slide 16 text

spread operator ES6 ...vals

Slide 17

Slide 17 text

ES6 function myFunction(x, y, z) { var args = [0, 1, 2]; myFunction(... var arr = [3, 4, 5]; [0, 1, 2].push( var middle = [‘b’, ‘c’ var arr = ['a', // [‘a’, ‘b’, ‘c’, ‘d’, ‘e’ function myFunction(x, y, z) { } var args = [0, 1, 2]; myFunction.apply(null, args); var arr = [3, 4, 5]; [0, 1, 2].concat(arr, [6]); ES5 spread operator developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_operator

Slide 18

Slide 18 text

default params ES6 function(foo=“baz”) {

Slide 19

Slide 19 text

ES6 function setColor(el, color=‘red’) { el.style.color = color; } var el = document.body; setColor(el); setColor(el, ’papayawhip’); function setColor(el, opt_Color) { el.style.color = opt_Color || ‘red’; } ES5 default function params developer.mozilla.org/docs/Web/JavaScript/Reference/Functions/Default_parameters

Slide 20

Slide 20 text

arrow functions ES6 (p1, p2) => { ... }

Slide 21

Slide 21 text

var a = ['Fe', 'Ne', 'Pt', 'Au']; var lens = a.map(function(s) { return s.length; }); Arrow functions

Slide 22

Slide 22 text

var a = ['Fe', 'Ne', 'Pt', 'Au']; var lens = a.map(function(s) { return s.length; }); Arrow functions

Slide 23

Slide 23 text

var a = ['Fe', 'Ne', 'Pt', 'Au']; var lens = a.map((s) => { return s.length; }); Arrow functions

Slide 24

Slide 24 text

var a = ['Fe', 'Ne', 'Pt', 'Au']; var lens = a.map((s) => s.length); Arrow functions

Slide 25

Slide 25 text

var a = ['Fe', 'Ne', 'Pt', 'Au']; var lens = a.map(s => s.length); Arrow functions

Slide 26

Slide 26 text

ES6 var myFunc = () => { return ‘expression!’; }; var myFunc2 = () => ‘expression!’; addEventListener(e => { console.log(‘func expression’); }; var myFunc = function() { return ‘func expression’; }; addEventListener(function(e) { console.log(‘func expression’); }); ES5 arrow functions developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

Slide 27

Slide 27 text

Polymer({ is: 'x-foo', highlight: function() { this.classList.add('highlight'); setTimeout(function() { this.classList.remove('highlight'); }, 300); } });

Slide 28

Slide 28 text

Ouch! this === window Polymer({ is: 'x-foo', highlight: function() { this.classList.add('highlight'); setTimeout(function() { this.classList.remove('highlight'); }, 300); } });

Slide 29

Slide 29 text

Polymer({ is: 'x-foo', highlight: function() { this.classList.add('highlight'); setTimeout(function() { this.classList.remove('highlight'); }.bind(this), 300); } });

Slide 30

Slide 30 text

Polymer({ is: 'x-foo', highlight: function() { this.classList.add('highlight'); setTimeout(function() { this.classList.remove('highlight'); }.bind(this), 300); } });

Slide 31

Slide 31 text

Arrow functions: Polymer({ is: 'x-custom', highlight: function() { this.classList.add('highlight'); setTimeout(() => { this.classList.remove('highlight'); }, 300); } }); lexical scoping

Slide 32

Slide 32 text

Arrow functions: Polymer context Polymer({ is: 'x-custom', highlight: function() { this.classList.add('highlight'); setTimeout(() => { this.classList.remove('highlight'); }, 300); } }); lexical scoping

Slide 33

Slide 33 text

object literal shorthand ES6

Slide 34

Slide 34 text

ES6 var Person = { get name() { return ‘Eric Bidelman’; }, showName() { alert(this.name); }, // Computed properties! get [‘foo’ + ‘bar’]() { return ‘foobar!’; } // Person.foobar === ‘foobar!’ var Person = { get name() { return ‘Eric Bidelman’; }, showName: function() { alert(this.name); } } ES5 object literal shorthand developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Method_definitions

Slide 35

Slide 35 text

Polymer({ get is() { return 'my-element'; } properties: { active: { type: Boolean, value: false, observer: '_activeChanged' } }, ready() { ... }, attached() { ... }, _activeChanged(newVal, oldVal) { ... } }); Object literal shorthand

Slide 36

Slide 36 text

Polymer({ get is() { return 'my-element'; } properties: { active: { type: Boolean, value: false, observer: '_activeChanged' } }, ready() { ... }, attached() { ... }, _activeChanged(newVal, oldVal) { ... } }); Object literal shorthand Polymer context Can use shorthand method naming in Polymer() constructor

Slide 37

Slide 37 text

template strings ES6 `I ${affection} Polymer!`

Slide 38

Slide 38 text

@ebidel @polymer #polymersummit Multiline strings other languages have it

Slide 39

Slide 39 text

@ebidel @polymer #polymersummit Multiline strings // PHP heredoc $text = <<

Slide 40

Slide 40 text

@ebidel @polymer #polymersummit Multiline strings // PHP heredoc $text = <<

Slide 41

Slide 41 text

@ebidel @polymer #polymersummit Multiline strings // PHP heredoc $text = <<

Slide 42

Slide 42 text

let html = ` <style> :host { ... } </style> <h2>Header content</h2> <content></content> `; let el = document.querySelector(‘my-element'); el.createShadowRoot().innerHTML = html; Multi-line template strings creating Shadow DOM from HTML snippets

light dom

Demo:

Slide 43

Slide 43 text

let html = ` <style> :host { ... } </style> <h2>Header content</h2> <content></content> `; let el = document.querySelector(‘my-element'); el.createShadowRoot().innerHTML = html; Multi-line template strings Polymer context creating Shadow DOM from HTML snippets

light dom

Demo:

Slide 44

Slide 44 text

let host = "https://api.github.com"; let org = "Polymer"; let repo = "polymer"; let url = `${host}/repos/${org}/${repo}/issues`; Template strings: string interpolation

Slide 45

Slide 45 text

let host = "https://api.github.com"; let org = "Polymer"; let repo = "polymer"; let url = `${host}/repos/${org}/${repo}/issues`; Template strings: string interpolation

Slide 46

Slide 46 text

function get(strs, …vals) { let url = vals.reduce((prev, val, i) => prev + strs[i] + val, ''); // TODO: fetch url. } Tagged template strings metaprogramming example Demo: get`${host}/repos/${org}/${repo}/issues`;

Slide 47

Slide 47 text

function get(strs, …vals) { let url = vals.reduce((prev, val, i) => prev + strs[i] + val, ''); // TODO: fetch url. } Tagged template strings metaprogramming example Demo: Run custom function over output string get`${host}/repos/${org}/${repo}/issues`;

Slide 48

Slide 48 text

Count: {{5 + 5}}
{{lastName}}, {{firstName}} 1.0 doesn’t have binding expressions :(

Slide 49

Slide 49 text

Expressions in bindings? Count: ${5 + 5}
${lastName}, ${firstName}
${users[1].name}
var t = document.querySelector('#t'); t.set('model.firstName', 'John'); t.set('model.lastName', 'Doe'); t.set('model.users', [{name: 'Tom'}, {name:'Bob'}]); Demo: POC using template strings as primitive “bindings”

Slide 50

Slide 50 text

Polymer context Expressions in bindings? Count: ${5 + 5}
${lastName}, ${firstName}
${users[1].name}
var t = document.querySelector('#t'); t.set('model.firstName', 'John'); t.set('model.lastName', 'Doe'); t.set('model.users', [{name: 'Tom'}, {name:'Bob'}]); Demo: POC using template strings as primitive “bindings”

Slide 51

Slide 51 text

classes ES6 class MyClass {...}

Slide 52

Slide 52 text

Yesterday’s class syntax function GitHubIssues(config) { this.org = config.org; this.repo = config.repo; }; GitHubIssues.prototype.list = function(opt_sort) { var url = 'https://api.github.com/repos/' + this.org + '/' + this.repo + '/issues?sort=' + (opt_sort || 'update'); return fetch(url).then(function(response) { return response.json(); }).then(function(issues) { console.info('Issues from ' + this.org + '/' + this.repo); issues.forEach(function(issue) { console.log(issue.url, issue.title); }); return issues; }.bind(this)); } var gh = new GitHubIssues({org: 'Polymer', repo: 'polymer'}); gh.list(); ES5 Demo:

Slide 53

Slide 53 text

class GithubIssues { constructor({org, repo}) { this.org = org; this.repo = repo; } list(sort='update') { let url = `https://api.github.com/repos/${this.org}/${this.repo}/issues?sort=${this.sort}`; return fetch(url).then(response => response.json()).then(issues => { console.info(`Issues from ${this.org}/${this.repo}`); issues.forEach(issue => console.log(issue.url, issue.title)); return issues; }); } } var gh = new GitHubIssues({org: 'Polymer', repo: 'polymer'}); gh.list(); Demo: Today’s class syntax ES6

Slide 54

Slide 54 text

class GithubIssues { constructor({org, repo}) { this.org = org; this.repo = repo; } list(sort='update') { let url = `https://api.github.com/repos/${this.org}/${this.repo}/issues?sort=${this.sort}`; return fetch(url).then(response => response.json()).then(issues => { console.info(`Issues from ${this.org}/${this.repo}`); issues.forEach(issue => console.log(issue.url, issue.title)); return issues; }); } } var gh = new GitHubIssues({org: 'Polymer', repo: 'polymer'}); gh.list(); Demo: Today’s class syntax ES6

Slide 55

Slide 55 text

class GithubIssues { constructor({org, repo}) { this.org = org; this.repo = repo; } list(sort='update') { let url = `https://api.github.com/repos/${this.org}/${this.repo}/issues?sort=${this.sort}`; return fetch(url).then(response => response.json()).then(issues => { console.info(`Issues from ${this.org}/${this.repo}`); issues.forEach(issue => console.log(issue.url, issue.title)); return issues; }); } } var gh = new GitHubIssues({org: 'Polymer', repo: 'polymer'}); gh.list(); Demo: Today’s class syntax ES6

Slide 56

Slide 56 text

class GithubIssues { constructor({org, repo}) { this.org = org; this.repo = repo; } list(sort='update') { let url = `https://api.github.com/repos/${this.org}/${this.repo}/issues?sort=${this.sort}`; return fetch(url).then(response => response.json()).then(issues => { console.info(`Issues from ${this.org}/${this.repo}`); issues.forEach(issue => console.log(issue.url, issue.title)); return issues; }); } } var gh = new GitHubIssues({org: 'Polymer', repo: 'polymer'}); gh.list(); Demo: Today’s class syntax ES6

Slide 57

Slide 57 text

class GithubIssues { constructor({org, repo}) { this.org = org; this.repo = repo; } list(sort='update') { let url = `https://api.github.com/repos/${this.org}/${this.repo}/issues?sort=${this.sort}`; return fetch(url).then(response => response.json()).then(issues => { console.info(`Issues from ${this.org}/${this.repo}`); issues.forEach(issue => console.log(issue.url, issue.title)); return issues; }); } } var gh = new GitHubIssues({org: 'Polymer', repo: 'polymer'}); gh.list(); Demo: Today’s class syntax ES6

Slide 58

Slide 58 text

class GithubIssues { constructor({org, repo}) { this.org = org; this.repo = repo; } list(sort='update') { let url = `https://api.github.com/repos/${this.org}/${this.repo}/issues?sort=${this.sort}`; return fetch(url).then(response => response.json()).then(issues => { console.info(`Issues from ${this.org}/${this.repo}`); issues.forEach(issue => console.log(issue.url, issue.title)); return issues; }); } } var gh = new GitHubIssues({org: 'Polymer', repo: 'polymer'}); gh.list(); Demo: Today’s class syntax ES6

Slide 59

Slide 59 text

Defining custom elements from a class class StockTicker extends HTMLElement { }

Slide 60

Slide 60 text

Defining custom elements from a class class StockTicker extends HTMLElement { createdCallback() { this.createShadowRoot().innerHTML = ` :host { display: block; }
`; } }

Slide 61

Slide 61 text

Defining custom elements from a class class StockTicker extends HTMLElement { createdCallback() { this.createShadowRoot().innerHTML = ` :host { display: block; }
`; } updateQuotes() { let url = `https://api.finance.com?q=${this.symbols}`; return fetch(url).then(…); } }

Slide 62

Slide 62 text

Defining custom elements from a class class StockTicker extends HTMLElement { createdCallback() { this.createShadowRoot().innerHTML = ` :host { display: block; }
`; } updateQuotes() { let url = `https://api.finance.com?q=${this.symbols}`; return fetch(url).then(…); } } document.registerElement('stocker-ticker', StockTicker);

Slide 63

Slide 63 text

Polymer elements from a class class StockTicker { beforeRegister() { this.is = 'stock-ticker'; this.properties = { symbols: {type: Array, observer: ’_updateQuotes’} }; } created() {} // Everything else is business as usual. ready() {} attached() {} ... _updateQuotes() {} } Polymer(StockTicker);

Slide 64

Slide 64 text

Polymer elements from a class Polymer context class StockTicker { beforeRegister() { this.is = 'stock-ticker'; this.properties = { symbols: {type: Array, observer: ’_updateQuotes’} }; } created() {} // Everything else is business as usual. ready() {} attached() {} ... _updateQuotes() {} } Polymer(StockTicker);

Slide 65

Slide 65 text

Polymer elements from a class Polymer context class StockTicker { beforeRegister() { this.is = 'stock-ticker'; this.properties = { symbols: {type: Array, observer: ’_updateQuotes’} }; } created() {} // Everything else is business as usual. ready() {} attached() {} ... _updateQuotes() {} } Polymer(StockTicker);

Slide 66

Slide 66 text

Polymer elements from a class Polymer context class StockTicker { beforeRegister() { this.is = 'stock-ticker'; this.properties = { symbols: {type: Array, observer: ’_updateQuotes’} }; } created() {} // Everything else is business as usual. ready() {} attached() {} ... _updateQuotes() {} } Polymer(StockTicker);

Slide 67

Slide 67 text

Polymer elements from a class Polymer context class StockTicker { beforeRegister() { this.is = 'stock-ticker'; this.properties = { symbols: {type: Array, observer: ’_updateQuotes’} }; } created() {} // Everything else is business as usual. ready() {} attached() {} ... _updateQuotes() {} } Polymer(StockTicker);

Slide 68

Slide 68 text

Polymer elements from a class Polymer context class StockTicker { beforeRegister() { this.is = 'stock-ticker'; this.properties = { symbols: {type: Array, observer: ’_updateQuotes’} }; } created() {} // Everything else is business as usual. ready() {} attached() {} ... _updateQuotes() {} } Polymer(StockTicker);

Slide 69

Slide 69 text

Build for production today

Slide 70

Slide 70 text

vulcanize index.html --inline-script --inline-css Build for production today

Slide 71

Slide 71 text

vulcanize index.html --inline-script --inline-css Build for production today | \ crisper -h index.v.html -j app.js;

Slide 72

Slide 72 text

vulcanize index.html --inline-script --inline-css Build for production today | \ crisper -h index.v.html -j app.js; babel app.js -o app.js

Slide 73

Slide 73 text

+

Slide 74

Slide 74 text

unsplash.com IT’S A BEAUTIFUL FUTURE

Slide 75

Slide 75 text

@ebidel @polymer #polymersummit +Eric Bidelman @ebidel ‣ Demo code: ‣ ES6 support ‣ babeljs.io ‣ ES6 in depth ‣ Imports Module Loader (IMD) ‣ Codelabs upstairs!