15:00

Web Components

Why you're already an expert

Why?

Components Today

<link rel="stylesheet" type="text/css" href="my-widget.css" />
<script src="my-widget.js"></script>

<div data-my-widget />

$(function() {
  $('[data-my-widget]').myWidget();
});
div.innerHTML = '<div data-my-widget />'

$(div).find('[data-my-widget]').myWidget(); // again...
<div data-my-widget>
  <div class="my-widget-foobar">
      <input type="text" class="my-widget-text" />
      <button class="my-widget-button">Go</button>
  </div>
</div>

Web Components

<link rel="import" href="my-widget.html" />

<my-widget />
div.innerHTML = '<my-widget />';
<my-widget>
  #document-fragment
    <div>
      <input type="text" />
      <button>Go</button>
    </div>
</my-widget>

DOM Elements

You're already an expert

Elements can be instantiated with markup

<input type="text" />

Elements can be instantiated with JS


var input = document.createElement('input');

el.innerHTML = '<input type="text" />';

Elements are instances


input instanceof HTMLInputElement; // true

div instanceof HTMLDivElement; // true

Elements perform their own initialisation


el.innerHTML = '<input type="text" value="foobar" />';

el.querySelector('input').value; // "foobar"

Elements can respond to attribute changes


input.setAttribute('value', 'Foobar')

input.value; // "Foobar"

Elements can have hidden internal DOM structures




<input type="date" />

dateInput.children.length; // 0

Elements have access to child elements



<select>
  <option>1</option>
  <option>2</option>
  <option>3</option>
</select>

Elements can have their own private styles




(Notice you don't need to do this)

<link rel="stylesheet" type="text/css" href="calendar.css" />

Elements can provide style hooks to their internals

dialog::backdrop {
  background: black;
}

Custom Elements

Register a new custom element

var MyElement = document.register('my-element');

Custom elements can be instantiated with markup

<my-element />

Custom elements can be instantiated with JS


document.createElement('my-element');

el.innerHTML = '<my-element />';

new MyElement();

Custom elements are instances

document.create('my-element') instanceof MyElement; // true

Custom elements can perform their own initialisation


document.register('my-element', {
  prototype: Object.create(HTMLElement.prototype, {
    createdCallback: {
      value: function() {
        this.innerHTML = '<h1>ELEMENT CREATED!</h1>';
      }
    }
})
});

Custom elements can respond to attribute changes


document.register('my-element', {
  prototype: Object.create(HTMLElement.prototype, {
    attributeChangedCallback: {
      value: function(attr, oldVal, newVal) {
        this.innerHTML = '<h1>ATTRIBUTE CHANGED!</h1>';
      }
    }
})
});

Shadow DOM

Custom elements can have hidden internal DOM structures


createdCallback: {
  value: function() {
    var shadow = this.createShadowRoot();
    shadow.innerHTML = "<h1>SHADOW DOM!</h1>";
  }
}

Custom elements have access to child elements


<my-element>
  <i>hello</i>
  <i>world</i>
</my-element>

createdCallback: {
  value: function() {
    var shadow = this.createShadowRoot();
    shadow.innerHTML = 'The <i> tags are: <content select="i" />';
  }
}

Encapsulated Styles

Custom elements have encapsulated styles by default


shadow = this.createShadowRoot();
shadow.innerHTML =
  "<style>span { color: green; }</style>" +
  "<span>I'm green</span>";

<my-element />
<span>I'm not green</span>

Custom elements can provide style hooks to their internals


createdCallback: {
  value: function() {
    var shadow = this.createShadowRoot();
    shadow.innerHTML = 'Hello <em part="world">World</em>';
  }
}

my-element::part(world) {
  color: green;
}
  • Simple
  • Consistent
  • Reusable
  • Encapsulated
  • Composable

Just the beginning

chrome://flags


Enable "experimental Web Platform features"

Polyfills


Google's Polymer

Mozilla's X-Tag

Components


Polymer Elements

Polymer UI Elements

Brick

X-Tag Registry

Open the console and experiment

Thank you!

Slides: bit.ly/alreadyanexpert