The document discusses the emerging web components standards that enable encapsulation, separation of concerns, and element portability. It covers the main web components APIs including templates, imports, shadow DOM, and custom elements. Templates allow declaring reusable DOM fragments. Imports allow loading additional HTML documents. Shadow DOM encapsulates DOM parts and prevents style leakage. Custom elements enable extending or creating custom HTML elements. While browser support is still developing, web components offer powerful tools for building reusable components in a standardized way.
6. About Me
• sparXys CEO and senior consultant
• Microsoft MVP in the last 9 years
• Pro Single Page Application Development (Apress) co-author
• 4 Microsoft Official Courses (MOCs) co-author
• GDG Rishon and AngularUP co-organizer
7. Agenda
• The Problems We Faced
• Web Components APIs
• Templates
• Imports
• Shadow DOM
• Custom Elements
9. 2. Poor Separation of Concerns
You want HTML, CSS and
JavaScript to work together
You end up with a mess
10. 3. No Native Templates
• Store HTML in hidden DOM element and show it
• Use script tag as a template holder:
<script id=”myTemplate” type=”text/template”>
<div>
…
</div>
</script>
11. 4. Bundling is Hard
• You want to bundle a complex component
The component includes HTML, CSS and JavaScript
how would you do that?
• Use a server side mechanism?
• Bundler? (Webpack/Browserify)
13. What if we could teach the
browser new elements?
14. Each Element Instance
• Will be a DOM element
• Creates its own DOM tree
• Can be accessed and manipulated using DOM functions or its own
API
• Is a JavaScript object
• Is this possible?
15. Web Components to the Rescue
• Natively-supported, standardized JavaScript components
• Some general goals:
Code Reuse Encapsulation
Separation of
Concerns
Composition Theming Expressive Semantic
16. The Web Components Standard
• Reusable DOM fragmentsTemplates
• Load HTML declarativelyImports
• DOM encapsulationShadow DOM
• Create your own elements
Custom
Elements
18. Setting The Environment
• We will use the webcomponents.js Polyfill
• A real world tested Polyfill
• Download:
• https://github.com/webcomponents/webcomponentsjs/
• Or install using your favorite package manager
• Make sure the Polyfill script runs first
21. Templates
• HTML element – template
• Can be used to instantiate document fragments
• Can wrap HTML, style tags and script tags
• No data binding support out of the box!
<template id=”myTemplate”>
<div>
…
</div>
</template>
22. Cloning a Template
• Select the template and extract its content
• Using its content property
• Use the importNode function to get the cloned content
• Only when the clone is appended to the DOM
• The style and JavaScript are executed
• Resources like images are retrieved from the server
23. Cloning a Template - Example
<template id=”myTemplate”>
…
</template>
// check template support
if ('content' in document.createElement('template')) {
// get the template
let template = document.getElementById(‘myTemplate’);
// clone the template
let clone = document.importNode(template.content, true);
// use the clone
elm.appendChild(clone);
}
25. The Slot Element
• Placeholder inside a web component
• Lets you inject separate DOM trees inside a component
• Named slot is used to expose more then one slot in a component
• Can be partnered with template elements
26. Combining Slot and Template Elements
<template id=”myTemplate”>
<div>
<slot name=“header"></slot>
<slot name="description"></slot>
</div>
</template>
27. Imports
• Load additional HTML documents
• Without using Ajax
• A new type of link tag
• Use the rel attribute with the import type:
<link rel=”import” href=”myImport.html”>
28. Imports and Bundling
• HTML Imports are intended to be used as packaging mechanism
• Enable to bundle a full component into one HTML file
• The HTML can include scripts and CSS styles
• The whole bundle can be retrieved in one single call
29. Imports and The DOM
• Importing a document doesn’t include it into the DOM
• It will parse it in memory and load all the additional resources
• Use the import property of the link tag:
let content = document.querySelector(‘link[rel=”import”]’).import;
31. Import Additional Notes
• Scripts running inside the import can reference the containing
document by calling document.currentScript.ownerDocument
• CORS constraints apply to documents imported from other domains
32. A Few Words About Script Modules
• Scripts that are treated as ECMAScript modules
• Module scripts don’t block the HTML parser
• Resembles script defer attribute
• Already implemented in most of the browsers
• Probably will replace the import standard
<script type=“module”>
import {someFunc} from './utils.js';
someFunc('Modules are pretty cool.');
</script>
33. Shadow DOM
• Encapsulate DOM parts
• The browser will know how to present those parts
• The browser won’t show the encapsulated parts in the source code
• Creates a boundary between the component and its user
34. The Problems Shadow DOM Tries to Solve
• Components/widgets encapsulation
• Style leakage
• Leaks from one component to another
• Leaks from imported 3th party library/framework
• Global DOM
• id or class attributes all over the place
35. Shadow DOM in The Browser
<video src="media/myVideo.mp4" controls></video>
<input type="date">
37. Shadow DOM – Cont.
• Use the attachShadow function to wrap an element as a shadow root:
• Mode property:
• open - elements of the shadow root are accessible from the outside using
element.shadowRoot
• closed - denies any access to node(s) inside the shadow root
let host = document.getElementByIt(‘shadowDOMHost’);
let root = host.attachShadow({mode: 'open'});
root.innerHTML = ‘<div>Lurking in the shadows</div>’;
38. Styling Shadow DOM
• Shadow DOM can have inline styles
• Using :host, :host() and :host-context pseudo-classes
• ::slotted() pseudo-element
<div name="myElement">
<style>
:host {
border: 1px solid lightgray;
}
</style>
<template>...</template>
</div>
40. Custom Elements
• Enable to extend or create custom HTML elements
• Defined using the customElements.define function:
or extend an existing element:
let myInput = window.customElements.define(‘my-input’,
class x extends HTMLElement {…});
let myInput = window.customElements.define(‘my-input’,
class y extends HTMLInputElement {...});
41. Custom Elements – Naming
• You can create named elements (almost) any way you want:
• Same naming rules as other HTML tags
• There must be a dash (“-”) in the name
• To future-proof the name against the HTML standard
• To avoid naming collisions
42. Custom Elements – Usage
• Use the element in your DOM:
or use the createElement function:
<my-input></my-input>
let elm = document.createElement(‘my-input’);
43. Custom Element Life Cycle Events
• connectedCallback
• disconnectedCallback
• attributeChangedCallback
• adoptedCallback
class MyInput extends HTMLElement {
constructor() {
super();
// your initialization code goes here
}
connectedCallback() {…}
disconnectedCallback() {…}
attributeChangedCallback() {…}
adoptedCallback() {…}
}
44. Observing Attribute Changes
• First list all the observed properties
• Use the observedAttributes getter
• Wire the attributeChangedCallback
• Will be called for every attribute that changes
class MyInput extends HTMLElement {
constructor() {
super();
// your initialization code goes here
}
static get observedAttributes() {
return ['attrName'];
}
attributeChangedCallback(name, oldValue, newValue) {
…
}
}
45. customElements Registry
• Includes API to
• Define custom elements using the define function
• Get custom element definition using the get function
• Understand if a custom element is defined using the whenDefined function
• Useful to defer work until the elements are really defined
47. The Current State of Web Components
• Still not a recommendation (yet)
• Browser support:
http://caniuse.com/#search=web%20components
• Known web component libraries:
Polymer X-Tag Stencil Slim.js Skate.js
48. Summary
• Web Components are emerging standards that enable:
• Encapsulation
• Separation of Concerns
• Element portability
• And more
• They are still in development!