Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Using ES6 with Polymer

Eric Bidelman
September 15, 2015

Using ES6 with Polymer

Polymer Summit 2015 presentation. How to use new ES6 features to build Polymer elements/apps.

Video: https://www.youtube.com/watch?v=bX3_tN23M_Y

Eric Bidelman

September 15, 2015
Tweet

More Decks by Eric Bidelman

Other Decks in Technology

Transcript

  1. @ebidel @polymer #polymersummit On deck agenda ‣Intro to small ES6

    features ‣Defining Polymer elements using classes
  2. <content> e.path content.getDistributedNodes(); <link rel=“import”> <custom-element> document.registerElement(‘custom-element’); <style> :host {

    display: block; } ::content > * { color: blue; } </style> <template> <button is=”mega-button”> el.createShadowRoot(); el.shadowRoot :unresolved { opacity: 0; }
  3. behaviors: [SwipBehavior] on-tap=“_handleTap” <template is=“dom-repeat”> <dom-module id=“my-element”> Polymer({is:‘my-element’}); <style> :host

    { } .warning { color: var( } </style> <div class=“layout horizontal”> <b>{{fooBar}}</b> <body unresolved> <template is=“dom-if”> observers: [ ‘_update(one, two, thre ] Polymer.Base.importHref()
  4. @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
  5. 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
  6. 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
  7. var a = ['Fe', 'Ne', 'Pt', 'Au']; var lens =

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

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

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

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

    a.map(s => s.length); Arrow functions
  12. 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
  13. Ouch! this === window Polymer({ is: 'x-foo', highlight: function() {

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

    this.classList.add('highlight'); setTimeout(() => { this.classList.remove('highlight'); }, 300); } }); lexical scoping
  15. 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
  16. Polymer({ get is() { return 'my-element'; } properties: { active:

    { type: Boolean, value: false, observer: '_activeChanged' } }, ready() { ... }, attached() { ... }, _activeChanged(newVal, oldVal) { ... } }); Object literal shorthand
  17. 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
  18. @ebidel @polymer #polymersummit Multiline strings // PHP heredoc $text =

    <<<EOT First line second line EOT; other languages have it
  19. @ebidel @polymer #polymersummit Multiline strings // PHP heredoc $text =

    <<<EOT First line second line EOT; # Py triple quote str text = """First line second line """ other languages have it
  20. @ebidel @polymer #polymersummit Multiline strings // PHP heredoc $text =

    <<<EOT First line second line EOT; # Py triple quote str text = """First line second line """ other languages have it // ES6 template string let text = `First line second line`;
  21. <script> let html = ` <style> :host { ... }

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

    </style> <h2>Header content</h2> <content></content> `; let el = document.querySelector(‘my-element'); el.createShadowRoot().innerHTML = html; </script> Multi-line template strings Polymer context creating Shadow DOM from HTML snippets <my-element> <p>light dom</p> </my-element> Demo:
  23. let host = "https://api.github.com"; let org = "Polymer"; let repo

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

    = "polymer"; let url = `${host}/repos/${org}/${repo}/issues`; Template strings: string interpolation
  25. 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`;
  26. 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`;
  27. <span style=“display: {{show ? ‘block’ : ‘none’}}”> Count: <span>{{5 +

    5}}</span> <div data-name=“{{users[1].name}}”> <span>{{lastName}}, {{firstName}}</span> 1.0 doesn’t have binding expressions :(
  28. Expressions in bindings? <template is=“template-expression" id="t"> <span>Count: ${5 + 5}</span>

    <!-- Count: 10 --> <div>${lastName}, ${firstName}</div> <!-- Doe, John --> <div>${users[1].name}</div> <!-- Bob --> </template> <script> var t = document.querySelector('#t'); t.set('model.firstName', 'John'); t.set('model.lastName', 'Doe'); t.set('model.users', [{name: 'Tom'}, {name:'Bob'}]); </script> Demo: POC using template strings as primitive “bindings”
  29. Polymer context Expressions in bindings? <template is=“template-expression" id="t"> <span>Count: ${5

    + 5}</span> <!-- Count: 10 --> <div>${lastName}, ${firstName}</div> <!-- Doe, John --> <div>${users[1].name}</div> <!-- Bob --> </template> <script> var t = document.querySelector('#t'); t.set('model.firstName', 'John'); t.set('model.lastName', 'Doe'); t.set('model.users', [{name: 'Tom'}, {name:'Bob'}]); </script> Demo: POC using template strings as primitive “bindings”
  30. 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:
  31. 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
  32. 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
  33. 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
  34. 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
  35. 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
  36. 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
  37. Defining custom elements from a class class StockTicker extends HTMLElement

    { createdCallback() { this.createShadowRoot().innerHTML = ` <style>:host { display: block; }</style> <div id="quotes"><div>`; } }
  38. Defining custom elements from a class class StockTicker extends HTMLElement

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

    { createdCallback() { this.createShadowRoot().innerHTML = ` <style>:host { display: block; }</style> <div id="quotes"><div>`; } updateQuotes() { let url = `https://api.finance.com?q=${this.symbols}`; return fetch(url).then(…); } } document.registerElement('stocker-ticker', StockTicker);
  40. 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);
  41. 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);
  42. 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);
  43. 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);
  44. 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);
  45. 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);
  46. 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
  47. +

  48. @ebidel @polymer #polymersummit <thank-you> +Eric Bidelman @ebidel ‣ Demo code:

    ‣ ES6 support ‣ babeljs.io ‣ ES6 in depth ‣ Imports Module Loader (IMD) ‣ Codelabs upstairs!