Web Components are low-level primitives that let you define your own HTML Elements.
Custom Elements
Shadow Dom
Template
Native client templating
Scoping and encapsulation
Define new tags
Imports
Import HTML files
Template
Allows you to declare fragments of DOM which are parsed, inert at page load, and instantiated later at runtime.
<template id="sdtemplate"> <style> p { color: orange; } </style> <p>I´m in a template</p> </template>
Custom elements
Allows you to create new HTML tags with custom properties and behaviour
var XFooProto = Object.create(HTMLElement.prototype);
// 1. Give x-foo a foo() method.
XFooProto.foo = function() {
alert('foo() called');
};
// 2. Define a property read-only "bar".
Object.defineProperty(XFooProto, "bar", {value: 5});
// 3. Register x-foo's definition.
var XFoo = document.registerElement('x-foo', {prototype: XFooProto});
// 4. Instantiate an x-foo.
var xfoo = document.createElement('x-foo');
// 5. Add it to the page.
document.body.appendChild(xfoo);
Custom elements
Shadow Dom
Allows you to declare fragments of DOM which are parsed, inert at page load, and instantiated later at runtime.
Allows you to declare fragments of DOM which are parsed, inert at page load, and instantiated later at runtime.
v0 var shadow = element.createShadowRoot(); v1
var shadow = element.attachShadow();
Frameworks
Browser
Browser
WEB COMPONENTS
vs
I want to add a google map marker!
Too much code!
<div id="map"></div>
<script src=“http://maps.googleapis.com/maps/api/js?callback=mapReady">
</script>
<script>
var marker = null;
function getCurrentLocation(callback) {
navigator.geolocation.watchPosition(callback);
}
function addMarker(opts, info) {
var marker = new google.maps.Marker(opts);
var infoWindow = new google.maps.InfoWindow({content: info});
google.maps.event.addListener(marker, 'click', function() {
infoWindow.open(opts.map, marker);
});
return marker;
}
function mapReady() {
var container = document.querySelector('#map');
var map = new google.maps.Map(container, {
zoom: 14, disableDefaultUI: true
});
getCurrentLocation(function(pos) {
var current = new google.maps.LatLng(pos.coords.latitude,
pos.coords.longitude);
map.setCenter(current);
// Re-position marker or create new one.
if (marker) {
marker.setPosition(map.getCenter());
} else {
marker = addMarker({
position: current, map: map, title: 'Your location'
}, '<b>Your location</b>');
}
});
}
</script>
<google-map latitude="40.2"></google-map>
¿ is ready for production?
google music / youtube gaming / youtube / santatracker / ing australia / bbva
NOT A FRAMEWORK
<icon-toggle></icon-toggle>
<dom-module id="icon-toggle">
<template>
<article> Icon </article>
</template>
<script>
Polymer({
is: 'icon-toggle'
});
</script>
</dom-module>
Template and interface declaration
Properties and functions declaration
<dom-module id="icon-toggle">
<style> </style>
<template> <h1></h1></template>
</dom-module>
<script>
Polymer({
is: 'icon-toggle'
});
</script>
<template>
<p> [[ name ]] </p> // one-way
<my-comp value="{{ name }}"> // two-way
</my-comp>
</template>
<script>
Polymer({
is: 'icon-toggle',
properties: {
name: { type: String, value: 'Hola' }
}
});
</script>
Conditional
Repeating
<template is="dom-if" if="{{myBoolean}}">
<p> [[ name ]] </p>
<iron-input value="{{ name }}"></iron-input>
</template>
<template is="dom-repeat" items="{{myArray}}">
<p> [[ item.name ]] </p>
<my-cmp value="{{ item.name }}"></my-cmp>
</template>
Polymer({ is: 'my-comp', // has to be kebab-case properties: { my-prop: { type: String, value: 'test', notify: true, observer: 'myFunc', computed: '_getValue(name)' } } });
- Defines the type of the property
- Some Polymer tools expects concrete types
- String, Number, Array, Object
- Set the initial value of the property
- If it´s not defined, sets to 'undefined'
- Has lower priority than specified attributes
- Generates a '*-changed' event automatically
- Has to be true to two-way data communication
- Call the specified function when the value changes
- Usefull to react to changes on two-way communications
- Execute a function to set his own value
- Can`t be setted. Read-only value
- Reacts to specified properties changes
title: {
type: String,
computed: '_getTitle(name)'
},
_getTitle: function(){
return 'Mr.'+name;
}
<my-comp title="Juan"></my-comp>
...
title: {
type: String,
value: 'name'
}
Native events
<template>
<button on-tap="_myFunc"></button>
</template>
<script>
Polymer({
is:'...',
_myFunc: function() {
console.info("button clicked");
}
</script>
Inline events
<template>
<button></button>
</template>
<script>
Polymer({
is:'...',
listeners: {
'tap': '_myFunc'
},
_myFunc: function(){ console.info("tapped!"); }
})
</script>
Listeners object
native events
Polymer({
is:'...',
listeners: {
'tap': '_myFunc',
'my-custom-event': '_myOtherFunc'
},
_myFunc: function(){
this.fire('my-custom-event', { value: 5});
},
_myOtherFunc: function(data) {
console.info(data.value);
}
})
Listeners object + Polymer.fire
custom events
app-main
Polymer({ . . . })
binding
events
Focus on create custom variables for every css property that could be sensible of changes
my-component.css
:host {
background: var(--my-component-background-color, #ff0000);
color: var(--my-component-color, #cecece);
}
father-component.css
:host {
--my-component-background-color: #d3d3d3;
--my-component-color: #000000;
}
Allows the developer to easily generate a Polymer-element-like documentation, based on code comments and DDD (Demo Driven Development)
Polymer({
is:'...',
properties: {
/**
* show the name of the current user
*/
}
listeners: {
'tap': '_myFunc'
},
/**
* Function to inform about on-tap event and execution
*/
_myFunc: function(){ console.info("tapped!"); }
})
visual elements with material design
functional elements
Architectural elements