Web Components + Backbone
A Game-Changing Combination
Who Am I?
Andrew Rota
JavaScript Engineer,
JavaScript Modularity
By using small libraries –
components with a dedicated
purpose and a small surface
area – it becomes possible to
pick and mix, to swap parts of
our front end stack...
- Jimmy Breck-McKye, "The State of JavaScript in
2015"
Modularity in HTML == DOM Elements
<ul>
  <li>First Item</li>
  <li>Second Item</li>
</ul>
<ol>
  <li>First Item</li>
  <li>Second Item</li>
</ol>
<div class="header"></div>
<header></header>
<div id="nav"></div>
<nav></nav>
Libraries > frameworks?
- Jimmy Breck-McKye, "The State of JavaScript in
2015"
Libraries > frameworks?
- Jimmy Breck-McKye, "The State of JavaScript in
2015"
Native functionality > libraries
> frameworks.
- Me
But creating your own elements
isn't possible...
... until now.
Web Components
usher in a new era of
web development
based on
encapsulated and
interoperable custom
elements that extend
HTML itself. - Polymer Project
Web Components
Web Component Technologies
Custom Elements
HTML Templates
HTML Imports
Shadow DOM
Web Component Technologies
Custom Elements
HTML Templates
HTML Imports
Shadow DOM
Custom Elements
<my‐element>Hello World.</my‐element>
            
var MyElement = document.registerElement('my‐element', {
  prototype: Object.create(HTMLElement.prototype)
});
            
Web Component Technologies
Custom Elements
HTML Templates
HTML Imports
Shadow DOM
HTML Templates
<template id="my‐template">
    <p>Hello World.</p>
    <!‐‐ This image won't be downloaded on page load ‐‐>
    <img src="example.jpg" alt="Example">
</template>
document.importNode(
    document.getElementById('my‐template').content,
    true
);
Web Component Technologies
Custom Elements
HTML Templates
HTML Imports
Shadow DOM
HTML Imports
<link rel="import" href="/imports/my‐component.html">
Web Component Technologies
Custom Elements
HTML Templates
HTML Imports
Shadow DOM
Browser Shadow DOM
Shadow DOM
<div id="my‐element"></div><p>Light DOM.</p>
// Create Shadow Root
var s = document.getElementById('my‐element').createShadowRoot();
// Add Styles and Text
s.innerHTML += '<style>p { color: crimson; }</style>';
s.innerHTML += '<p>Shadow DOM.</p>';
Shadow DOM.
Light DOM.
<content>
<div id="my‐element"><p>Hello!</p></div>
var s = document.getElementById('my‐element').createShadowRoot();
s.innerHTML += '<p>Shadow DOM Start.</p>';
s.innerHTML += '<style>p { color: crimson; }</style>';
s.innerHTML += '<content></content>';
s.innerHTML += '<p>Shadow DOM End.</p>';
Shadow DOM Start.
Hello!
Shadow DOM End.
Web Component Technologies
Custom Elements
HTML Templates
HTML Imports
Shadow DOM
What Web Components Lack...
Application Structure
Server Interface
URL Router
Models/Collections + Events
...We Gain with Backbone
Application Structure
Server Interface
URL Router
Models/Collections + Events
Using Web
Component
Technologies
+
Backbone
Backbone + Custom Elements
document.registerElement('my‐custom‐element', {
  prototype: Object.create(HTMLElement.prototype)
});
Backbone.View.extend({
  tagName: 'my‐custom‐element'
});
Backbone + HTML Templates
Backbone.View.extend({
  template: document.importNode(
    document.getElementById('my‐template').content,
    true
  ),
  render: function() {
    this.el.innerHTML = this.template;
  }
});
Backbone + HTML Imports
<link rel="import" href="my‐custom‐component.html">
Backbone + Shadow DOM
Backbone.View.extend({
  initialize: function() {
    this.el.createShadowRoot();
  }
});
Using Web
Component
Technologies
+
Backbone
Using Web
Components
+
Backbone
polymer-project.org/docs/elements
x-tags.org
component.kitchen
customelements.io
Backbone View
+
Web Component
<paper‐toast>
<paper‐toast> API
<paper‐toast
  text="Your toast is ready!"
  duration="5000"
  autoCloseDisabled
  opened
></paper‐toast>
Element.show();
Element.dismiss();
Element.toggle();
Element.addEventListener('core‐overlay‐open‐completed', doSomething
Backbone.View.extend({
  tagName: 'paper‐toast',
  attributes: {
    text: 'Your toast is ready!',
    autoCloseDisabled: true,
    duration: '5000',
    opened: true
  },
  events: {
    'core‐overlay‐open‐completed': 'doSomething'
  },
  toggle: function() {
    this.el.toggle();
  }
});
<google‐map>
<google‐map> API
<google‐map
  zoom="10"
  latitude="42.3581"
  longitude="‐71.0636"
></google‐map>
Element.resize();
Element.clear();
Element.addEventListener('google‐map‐ready', doSomething);
Backbone.View.extend({
  tagName: 'google‐map',
  attributes: {
    latitude: '42.3581',
    longitude: '‐71.0636',
    zoom: '10'
  },
  events: {
    'google‐map‐ready': 'doSomething'
  },
  resize: function() {
    this.el.resize();
  }
});
Backbone.View.extend({
  initialize: function() {
    this.listenTo(this.model, 'change', this.moveMap );
  },
  tagName: 'google‐map',
  moveMap: function(model) {
    this.el.setAttribute('latitude', this.model.get('lat'));
    this.el.setAttribute('longitude', this.model.get('long'));
    this.el.setAttribute('zoom', this.model.get('zoom'));
  }
});
Building Web Components
for Backbone (or anything else)
├── hello‐world
├──── hello‐world.html
├──── hello‐world.js
└──── bower.json
            
<template id="my‐template">
  Hello, <content></content
</template>
<script src="hello‐world.js
var element = Object.create(HTMLElement.prototype);
element.createdCallback = function() {};
element.attachedCallback = function() {};
element.attributeChangedCallback = function(attr, oldVal, newVal) {}
element.detachedCallback = function() {};
document.registerElement('hello‐world', {
  prototype: element
});
<link
  rel="import"
  href="components/hello‐world/hello‐world.html
>
<!‐‐ [...] ‐‐>
<hello‐world>I'm a web component</
How It All Fits Together
Application + Components
Application
Component Component Component Component Component
Component Component Component Component Component
Component Component Component Component Component
Application + Components
Application + Components
Application + Components
< X >
< X >
Web Component All the Things??
<backboneconf‐app>
    <backboneconf‐menu></backboneconf‐menu>
    <backboneconf‐content></backboneconf‐content>
    <backboneconf‐footer></backboneconf‐footer>
</backboneconf‐app>
Probably Not (and that's OK)
I don't ever see us going all in
on Custom Elements for every
possible thing ... Use native
elements and controls when
possible and supplement with
custom elements.
- Joshua Peek, Github Programmer
Should I Componentize?
Does it encapsulate component-level logic?
Does it take the place of a native element?
Should it be portable?
Is it context independent?
Can the API be represented as attributes, methods, and events?
Small
Open for Extension
Documented
Unit Tested
Accessible
Idempotent
Best Practices
Can I Use???
Custom
Elements
HTML
Templates
HTML
Imports
Shadow
DOM
✓ ✓ ✓ ✓
✓ ✓ ✓ ✓
Flag ✓ Flag Flag
X ✓ X X
X X X X
Can I Use???
Custom
Elements
HTML
Templates
HTML
Imports
Shadow
DOM
✓ ✓ ✓ ✓
✓ ✓ ✓ ✓
✓ ✓ ✓ ✓
✓ ✓ ✓ ✓
✓ ✓ ✓ ✓
webcomponents.js
Towards a Component Driven Web
Thanks!
Resources
- WebComponents.org
- Web Components: A Tectonic Shift for Web Development by Eric Bidelman
- Web Components by Jarrod Overson and Jason Strimpel
- Ten Principles for Great General Purpose Web Components
Colophon
This presentation was built with Backbone.js, Shadow DOM, HTML
Templates, HTML Imports, and the Custom Element <slide‐content>
using Web Component Slides.

Web Components + Backbone: a Game-Changing Combination