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

Custom Elements Everywhere

Rob Dodson
August 25, 2017

Custom Elements Everywhere

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

If you're a mid to large size company, building your UI in Web Components and sharing it across teams on different stacks sounds like a great plan. In theory things should "just work," but reality often proves otherwise. What do we need to do to make sure our components work well with all of the major frameworks and conversely what do the frameworks need to do to work with our components? This talk explores both sides of the problem and lays out some best practices that both parties can use to ensure seamless interoperability.

Rob Dodson

August 25, 2017
Tweet

More Decks by Rob Dodson

Other Decks in Technology

Transcript

  1. TWO PARTS PART no. 1 What is a "good" Custom

    Element? PART no. 2 How should frameworks act?
  2. Do you know if there are any reference Custom Elements

    I could look at which live up to this standard? Not that I'm aware of.
  3. HowTo: Components A collection of educational custom elements that demonstrate

    best practices. Examples are meant to be read, interpreted, and ported to your own elements.
  4. super(); this.attachShadow({mode: 'open'}); this.shadowRoot.appendChild(template.conte } connectedCallback() { if (!this.hasAttribute('role')) this.setAttribute('role',

    'checkbox'); if (!this.hasAttribute('tabindex')) this.setAttribute('tabindex', 0); this._upgradeProperty('checked'); this._upgradeProperty('disabled'); this.addEventListener('keydown', this._onK The construtor is a good place to create Shadow DOM, though you should avoid touching any attributes or Light DOM children as they may not be available yet. connectedCallback fires when the element is inserted into the DOM. It's a good place to set the initial role, tabindex, internal state, and install event listeners. A user may set a property on an instance of an element, before its prototype has been connected to this class. The `_upgradeProperty` method
  5. If someone puts your element inside another shadow root, you'll

    have to figure out how to get your styles in there.
  6. export class CountWithShadow extends HTMLElement { constructor () { super();

    this.attachShadow({ mode: 'open' }); this.shadowRoot.appendChild(template.content.cloneNode(true)); } } customElements.define('x-count-with-shadow', CountWithShadow); Polymer Summit 2017
  7. export class CountWithoutShadow extends HTMLElement { constructor () { super();

    } connectedCallback() { this.appendChild(template.content.cloneNode(true)); } } customElements.define('x-count-without-shadow', Count); Polymer Summit 2017
  8. // Meanwhile, in a React component… render () { const

    { count } = this.state; // increments every second return ( <div> <x-count-with-shadow>{count}</x-count-with-shadow> <x-count-without-shadow>{count}</x-count-without-shadow> </div> ); } Polymer Summit 2017
  9. Create a shadow root if you want to self-apply styles.

    Place any children you create into a shadow root. Shadow DOM
  10. class CustomVideo extends HTMLElement { get preload() { const value

    = this.getAttribute('preload'); return value === null ? 'auto' : value; } set preload(value) { this.setAttribute('preload', value); } } Polymer Summit 2017
  11. class CustomVideo extends HTMLElement { get preload() { const value

    = this.getAttribute('preload'); return value === null ? 'auto' : value; } set preload(value) { this.setAttribute('preload', value); } } Polymer Summit 2017 default value
  12. class CustomVideo extends HTMLElement { get preload() { const value

    = this.getAttribute('preload'); return value === null ? 'auto' : value; } set preload(value) { this.setAttribute('preload', value); } } Polymer Summit 2017
  13. Accept primitive data as either attributes or properties. Reflect primitive

    data from attribute to property, and vice versa. Only accept rich data as properties. Do NOT reflect rich data from property to attribute. Attributes & Properties
  14. Do NOT dispatch events in response to the host setting

    a property (downward data flow).
  15. Do NOT dispatch events in response to the host setting

    a property (downward data flow). Do dispatch events in response to internal element activity. Events
  16. Manual The developer tells the framework how to pass data.

    Automated The framework determines how to pass data.
  17. React You can work around this by imperatively grabbing a

    reference to the element and setting the property on it.
  18. React You can work around this by imperatively grabbing a

    reference to the element and adding an event listener.
  19. amazing people Reviewers HowTo: Components team Sean Rob Jason Evan

    Dan Domenic Steve Dominic Surma Monica Ewa
  20. Thank You! Polymer Summit 2017 Rob Dodson @rob_dodson Images by

    Simon Child, Eucalyp, Edward Boatman from the Noun Project.