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

Using ES6 with Polymer

Avatar for Eric Bidelman 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

Avatar for Eric Bidelman

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!