SlideShare a Scribd company logo
+Web Components
Polymer
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
• Lead of JUG Dortmund
• Speaker, blogger & author
• Java Architect @ Canoo Engineering AG
• JavaOne Rockstar
• JSR Expert Group member www.guigarage.com@hendrikEbbers
Hendrik Ebbers
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
• UI magician
• Active speaker and writer
• Code Monkey @ Canoo Engineering AG
• http://blog.netopyr.com
@net0pyr
Michael Heinrichs
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Questions?
https://app.sli.do/event/xfb1afkm/ask
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Web Component
Spec
Polymer A first app Real World
Applications
Content
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
frontend code today
<li class="yt-shelf-grid-item yt-uix-shelfslider-item">

<div class="yt-lockup yt-lockup-grid yt-lockup-video vve-check clearfix"
data-context-item-id="naiLVvuPCAw"

data-visibility-tracking=
"CFEQpDAYBSITCM7Or_3JucMCFY6yHAodHk0ANiiOHkCMkLzc7-qi1J0B">

<div class="yt-lockup-dismissable">

<div class="yt-lockup-thumbnail contains-addto">

<a aria-hidden="true" href="/watch?v=naiLVvuPCAw"
class=" yt-uix-sessionlink spf-link "

data-sessionlink=
"itct=CFEQpDAYBSITCM7Or_3JucMCFY6yHAodHk0ANiiOHjIKZy1oaWdoLXJjaA">

<div class="yt-thumb video-thumb">

<img src="//i.ytimg.com/vi/naiLVvuPCAw/mqdefault.jpg"
width="196" height="110"/>

</div>

Web Applications
Today
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
frontend code today
<li class=" yt-uix-shelfslider-item">

<div class="yt-lockup yt-lockup-grid yt-lockup-video vve-check clearfix" data-context-item-id="naiLVvuPCAw"

data-visibility-tracking="CFEQpDAYBSITCM7Or_3JucMCFY6yHAodHk0ANiiOHkCMkLzc7-qi1J0B">

<div class="yt-lockup-dismissable">

<div class="yt-lockup-thumbnail contains-addto">

<a aria-hidden="true" href="/watch?v=naiLVvuPCAw" class=" yt-uix-sessionlink spf-link "

data-sessionlink="itct=CFEQpDAYBSITCM7Or_3JucMCFY6yHAodHk0ANiiOHjIKZy1oaWdoLXJjaA">

<div class="yt-thumb video-thumb">

<img src="//i.ytimg.com/vi/naiLVvuPCAw/mqdefault.jpg" width="196" height="110"/>

</div>

<span class="video-time" aria-hidden="true">1:21</span>

</a>

<span class="thumb-menu dark-overflow-action-menu video-actions">

<button onclick=";return false;"

class="yt-uix-button-reverse flip addto-watch-queue-menu spf-nolink hide-until-delayloaded yt-uix-button yt-uix-button-dark-overflow-action-menu yt-uix-button-size-default yt-uix-button-has-icon no-icon-markup yt-uix-button-empty"

aria-expanded="false" aria-haspopup="true" type="button">

<span class="yt-uix-button-arrow yt-sprite"></span>

<ul class="watch-queue-thumb-menu yt-uix-button-menu yt-uix-button-menu-dark-overflow-action-menu" style="display: none;">

<li role="menuitem" class="overflow-menu-choice addto-watch-queue-menu-choice addto-watch-queue-play-next yt-uix-button-menu-item"

data-action="play-next" onclick=";return false;" data-video-ids="naiLVvuPCAw">

<span class="addto-watch-queue-menu-text">Play next</span>

</li>

<li role="menuitem" class="overflow-menu-choice addto-watch-queue-menu-choice addto-watch-queue-play-now yt-uix-button-menu-item"

data-action="play-now" onclick=";return false;" data-video-ids="naiLVvuPCAw">

<span class="addto-watch-queue-menu-text">Play now</span>

</li>

</ul>

</button>

</span>

<button class="yt-uix-button yt-uix-button-size-small yt-uix-button-default yt-uix-button-empty yt-uix-button-has-icon no-icon-markup addto-button video-actions spf-nolink hide-until-delayloaded addto-watch-later-button-sign-in yt-uix-tooltip"

type="button" onclick=";return false;" title="Watch Later" role="button"

data-video-ids="naiLVvuPCAw" data-button-menu-id="shared-addto-watch-later-login"><span

class="yt-uix-button-arrow yt-sprite"></span></button>

<button class="yt-uix-button yt-uix-button-size-small yt-uix-button-default yt-uix-button-empty yt-uix-button-has-icon no-icon-markup addto-button addto-queue-button video-actions spf-nolink hide-until-delayloaded addto-tv-queue-button yt-uix-
tooltip"

type="button" onclick=";return false;" title="TV Queue" data-video-ids="naiLVvuPCAw"

data-style="tv-queue"></button>

</div>

<div class="yt-lockup-content">

<h3 class="yt-lockup-title">

<a href="/watch?v=naiLVvuPCAw"

class=" yt-ui-ellipsis yt-ui-ellipsis-2 yt-uix-sessionlink spf-link "

data-sessionlink="itct=CFEQpDAYBSITCM7Or_3JucMCFY6yHAodHk0ANiiOHjIKZy1oaWdoLXJjaA"

title="Polizisten hören Helene Fischer&#39;s &#39;Atemlos&#39; im Polizeiauto"

aria-describedby="description-id-439757"

dir="ltr">Polizisten hören Helene Fischer&#39;s&#39;Atemlos&#39; im Polizeiauto</a>

<span class="accessible-description" id="description-id-439757"> - Duration: 1:21.</span>

</h3>

<div class="yt-lockup-byline">by <a href="/user/djgreyhair class=" yt-uix-sessionlink spf-link g-hovercard" data-name=""

data-sessionlink="itct=CFEQpDAYBSITCM7Or_3JucMCFY6yHAodHk0ANiiOHg" data-ytid="UCCBrsuWhYxpwZYSTY7kkB4A">Spass MussSein</a>

</div>

<div class="yt-lockup-meta">

<ul class="yt-lockup-meta-info">

<li>3,542,577 views</li>

<li>6 months ago</li>

</ul>

</div>

</div>

</div>

</div>

</li>
Web Applications
Today
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
frontend code tomorrow
<shelf
title="Popular on YouTube - Switzerland"
subscribers=“128,657">
<shelf-grid-item
title="iPhone 6 Plus Bend Test"
url="https://www.youtube.com/watch?v=znK652H6yQM"
thumbnail="https://i.ytimg.com/vi_webp/znK652H6yQM/mqdefault.webp"
user="Unbox Therapy"
userUrl="https://www.youtube.com/user/unboxtherapy"
views="63,732,280"
time="4 months ago">
…


Web Applications
Tomorrow
Web Component
Spec
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Web Component Spec
• Specified by W3C
• Current state of spec can be found
online: 

http://www.w3.org/standards/techs/components#w3c_all
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Web Component Spec
• Divided in 4 parts:
• HTML Templates
• Shadow DOM
• Custom Elements
• HTML Imports
<template>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
<template>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
<template>
<div class="activity-stream">

<h2>Activities</h2>



<div class="activity">

<img class="icon" src="img/hendrik.jpeg" width="40" height="40">

<div class="time">Minutes ago</div>

<div class="content"><a>Hendrik</a> did this again.</div>

</div>


…
</div>


<div class="activity">

<img class="icon" src="img/michael.jpeg" width="40" height="40">

<div class="time">Seconds ago</div>

<div class="content"><a>Michael</a> had fun coding.</div>

</div>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
<template>
<div class="activity-stream">

<h2>Activities</h2>



<div class="activity">

<img class="icon" src="img/hendrik.jpeg" width="40" height="40">

<div class="time">Minutes ago</div>

<div class="content"><a>Hendrik</a> did this again.</div>

</div>


…
</div>


<div class="activity">

<img class="icon" src="img/michael.jpeg" width="40" height="40">

<div class="time">Seconds ago</div>

<div class="content"><a>Michael</a> had fun coding.</div>

</div>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
<template>
<div class="activity">



</div>


<img class="icon" src="img/michael.jpeg" width="40" height="40">

<div class="time">Seconds ago</div>

<div class="content"><a>Michael</a> had fun coding.</div>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
<template>
<template id="activity-template">

</template>
<div class="activity">



</div>
template tag


<img class="icon" src="img/michael.jpeg" width="40" height="40">

<div class="time">Seconds ago</div>

<div class="content"><a>Michael</a> had fun coding.</div>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
<template>
<div>

<img class="icon" src="" width="40" height="40">

<div class="time"></div>

<div class="content"></div>

</div>
<template id="activity-template">

</template>
<div class="activity">



</div>
copy boilerplate
template tag


<img class="icon" src="img/michael.jpeg" width="40" height="40">

<div class="time">Seconds ago</div>

<div class="content"><a>Michael</a> had fun coding.</div>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
<template>
<div>

<img class="icon" src="" width="40" height="40">

<div class="time"></div>

<div class="content"></div>

</div>
<template id="activity-template">

</template>
<div class="activity">



</div>
copy boilerplate
template tag
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
<template>
<template id="activity-template">

<div>

<img class="icon" src="" width="40" height="40">

<div class="time"></div>

<div class="content"></div>

</div>

</template>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
<template>
<template id="activity-template">

<div>

<img class="icon" src="" width="40" height="40">

<div class="time"></div>

<div class="content"></div>

</div>

</template>
var template = document.querySelector('#activity-template');
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
<template>
<template id="activity-template">

<div>

<img class="icon" src="" width="40" height="40">

<div class="time"></div>

<div class="content"></div>

</div>

</template>
var template = document.querySelector('#activity-template');
var clone = document.importNode(template.content, true);
use content property
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
<template>
document.body.appendChild(clone);
<template id="activity-template">

<div>

<img class="icon" src="" width="40" height="40">

<div class="time"></div>

<div class="content"></div>

</div>

</template>
var template = document.querySelector('#activity-template');
var clone = document.importNode(template.content, true);
use content property
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
<template>
<template id="activity-template">

<div>

<img class="icon" ng-src="{{item.iconSrc}}" width="40" height="40">

<div class="time">{{item.time}}</div>

<div class="content">{{item.content}}</div>

</div>

</template>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
<template>
<template id="activity-template">

<div>

<img class="icon" ng-src="{{item.iconSrc}}" width="40" height="40">

<div class="time">{{item.time}}</div>

<div class="content">{{item.content}}</div>

</div>

</template>
No Data Binding
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
<template>
22+ 26+ and
Android 4.4+
7.1+ 15+
Shadow Dom
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Shadow Dom
Web Component
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Shadow Dom
".content"".content"
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Shadow Dom
".content"".content"
document.querySelector(".content")
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Shadow Dom
".content"".content"
document.querySelector(".content")
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Shadow Dom
".content"".content"
.content {
color: blue;
}
document.querySelector(".content")
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Shadow Dom
".content"".content"
.content {
color: blue;
}
document.querySelector(".content")
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Shadow Dom
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Shadow Dom
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Shadow Dom
Host
Root
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Shadow Dom
visible to

the user
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Shadow Dom
visible to

the user
used during
rendering
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Shadow Dom
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Shadow Dom
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Shadow Dom
document.querySelector(".content")
.content {
color: blue;
}
".content" ".content"
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Shadow Dom
document.querySelector(".content")
.content {
color: blue;
}
".content" ".content"
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Shadow Dom
Host
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Shadow Dom
var root = host.createShadowRoot();
Host
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Shadow Dom
var root = host.createShadowRoot();
Host
Root
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Shadow Dom
var root = host.createShadowRoot();
Host
Root
root.appendChild(child1);
root.appendChild(child2);
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Shadow Dom
var root = host.createShadowRoot();
Host
Root
root.appendChild(child1);
root.appendChild(child2);
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Shadow Dom
Host
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Shadow Domvar root = host.createShadowRoot();
Host
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Shadow Domvar root = host.createShadowRoot();
Host
Root
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Shadow Domvar root = host.createShadowRoot();
Host
Root
var clone = document.importNode(
template.content, true);
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Shadow Domvar root = host.createShadowRoot();
Host
Root
var clone = document.importNode(
template.content, true);
Clone
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Shadow Domvar root = host.createShadowRoot();
Host
Root
var clone = document.importNode(
template.content, true);
root.appendChild(clone);
Clone
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Shadow Domvar root = host.createShadowRoot();
Host
Root
var clone = document.importNode(
template.content, true);
root.appendChild(clone);
Clone
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Shadow Dom
25+ and
Android 4.4+
15+
Custom
Elements
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Custom Elements
<div class="activity">
<a>Michael</a> had fun coding.
</div>
How do we store the icon source and time?
What is a <div> with the class “activity” anyway?
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Custom Elements
<div class="activity">
<a>Michael</a> had fun coding.
</div>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Custom Elements
<activity-card iconSrc="img/michael.jpg" time="Seconds ago">
<a>Michael</a> had fun coding.
</activity-card>
<div class="activity">
<a>Michael</a> had fun coding.
</div>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Custom Elements
var activityCardPrototype = Object.create(HTMLElement.prototype);
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Custom Elements
var activityCardPrototype = Object.create(HTMLElement.prototype);
Rough translation to Java
class ActivityCard extends HTMLElement {};
Class<ActivityCard> activityCardClass = ActivityCard.class;
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Custom Elements
var activityCardPrototype = Object.create(HTMLElement.prototype);
Rough translation to Java
class ActivityCard extends HTMLElement {};
Class<ActivityCard> activityCardClass = ActivityCard.class;
var options = {prototype: activityPrototype}
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Custom Elements
var activityCardPrototype = Object.create(HTMLElement.prototype);
Rough translation to Java
class ActivityCard extends HTMLElement {};
Class<ActivityCard> activityCardClass = ActivityCard.class;
ElementRegistrationOptions options = 

new ElementRegistrationOptions(activityCardClass);
var options = {prototype: activityPrototype}
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Custom Elements
document.registerElement("activity-card", options);
var activityCardPrototype = Object.create(HTMLElement.prototype);
Rough translation to Java
class ActivityCard extends HTMLElement {};
Class<ActivityCard> activityCardClass = ActivityCard.class;
ElementRegistrationOptions options = 

new ElementRegistrationOptions(activityCardClass);
var options = {prototype: activityPrototype}
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Custom Elements
document.registerElement("activity-card", options);
var activityCardPrototype = Object.create(HTMLElement.prototype);
document.registerElement("activity-card", options);
Rough translation to Java
class ActivityCard extends HTMLElement {};
Class<ActivityCard> activityCardClass = ActivityCard.class;
ElementRegistrationOptions options = 

new ElementRegistrationOptions(activityCardClass);
var options = {prototype: activityPrototype}
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Custom Elements
document.registerElement("activity-card", options);
var activityCardPrototype = Object.create(HTMLElement.prototype);
var options = {prototype: activityPrototype}
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Custom Elements
document.registerElement("activity-card", options);
var activityCardPrototype = Object.create(HTMLElement.prototype);
var options = {prototype: activityPrototype}
<activity-card iconSrc="img/michael.jpg" time="Seconds ago">
<a>Michael</a> had fun coding.
</activity-card>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Custom Elements
create attach detach
change
createdCallback
attachedCallback
detachedCallback
attributeChangedCallback

(attrName, oldVal, newVal)
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Custom Elements
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Custom Elementsvar activityPrototype = Object.create(HTMLElement.prototype);
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Custom Elementsvar activityPrototype = Object.create(HTMLElement.prototype);
activityPrototype.createdCallback = function() {
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Custom Elementsvar activityPrototype = Object.create(HTMLElement.prototype);
activityPrototype.createdCallback = function() {
var template = $("#activity-template");
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Custom Elementsvar activityPrototype = Object.create(HTMLElement.prototype);
activityPrototype.createdCallback = function() {
var template = $("#activity-template");
var clone = document.importNode(template.content, true);
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Custom Elementsvar activityPrototype = Object.create(HTMLElement.prototype);
activityPrototype.createdCallback = function() {
var template = $("#activity-template");
var clone = document.importNode(template.content, true);
var host = $(this);
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Custom Elementsvar activityPrototype = Object.create(HTMLElement.prototype);
activityPrototype.createdCallback = function() {
var template = $("#activity-template");
var clone = document.importNode(template.content, true);
var host = $(this);
$(".icon", clone).attr("src", host.attr("iconSrc"));
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Custom Elementsvar activityPrototype = Object.create(HTMLElement.prototype);
activityPrototype.createdCallback = function() {
var template = $("#activity-template");
var clone = document.importNode(template.content, true);
var host = $(this);
$(".icon", clone).attr("src", host.attr("iconSrc"));
$(".time", clone).text(host.attr("time"));
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Custom Elementsvar activityPrototype = Object.create(HTMLElement.prototype);
activityPrototype.createdCallback = function() {
var template = $("#activity-template");
var clone = document.importNode(template.content, true);
var host = $(this);
$(".icon", clone).attr("src", host.attr("iconSrc"));
$(".time", clone).text(host.attr("time"));
var shadow = this.createShadowRoot();
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Custom Elementsvar activityPrototype = Object.create(HTMLElement.prototype);
activityPrototype.createdCallback = function() {
var template = $("#activity-template");
var clone = document.importNode(template.content, true);
var host = $(this);
$(".icon", clone).attr("src", host.attr("iconSrc"));
$(".time", clone).text(host.attr("time"));
var shadow = this.createShadowRoot();
shadow.appendChild(clone);
};
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Custom Elementsvar activityPrototype = Object.create(HTMLElement.prototype);
activityPrototype.createdCallback = function() {
var template = $("#activity-template");
var clone = document.importNode(template.content, true);
var host = $(this);
$(".icon", clone).attr("src", host.attr("iconSrc"));
$(".time", clone).text(host.attr("time"));
var shadow = this.createShadowRoot();
shadow.appendChild(clone);
};
document.registerElement("activity-card", {prototype: activityPrototype});
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Custom Elements
35+ and
Android 4.4.4+
26+
Html Import
<!DOCTYPE html>

<html>

<head lang="en">

<meta charset="UTF-8">

<title>Activity Stream - Standard Web Component</title>

<link href="stylesheet.css" rel="stylesheet">

<script src="bower_components/jquery/dist/jquery.min.js"></script>

</head>

<body>

<template>

<style>

* {

font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;

}

.activity {

width: 500px;

height: 40px;

padding: 10px;

background-color: #f0f8ff;

font-size: small;

margin: 10px 0;

}

.activity .icon {

float: left;

border-radius: 100%;

}



.activity .time {

float: right;

color: #b7b7b7;

font-style: italic;

}

.activity .content {

margin-left: 60px;

}

</style>



<div class="activity">

<img class="icon" src="" width="40" height="40">

<div class="time"></div>

<div class="content"><content></content></div>

</div>

</template>





<script>



var activityPrototype = Object.create(HTMLElement.prototype);



activityPrototype.createdCallback = function() {

var template = document.querySelector('template');

var clone = document.importNode(template.content, true);



var host = $(this);

$(".icon", clone).attr("src", host.attr("iconSrc"));

$(".time", clone).text(host.attr("time"));



var shadowRoot = this.createShadowRoot();

shadowRoot.appendChild(clone);

};



// Register our new element

document.registerElement('activity-card', {

prototype: activityPrototype

});

</script>



<div class="activity-stream">

<h2>Activities</h2>

<activity-card iconSrc="../img/michael.jpeg" time="Seconds ago">

<a href="profiles/michael">Michael</a> had fun writing web components.

</activity-card>

<activity-card iconSrc="../img/hendrick.jpeg" time="Minutes ago">

<a href="profiles/hendrick">Hendrick</a> blogged on <a href="http://guigarage.com">GuiGarage</a>.

</activity-card>

<activity-card iconSrc="../img/michael.jpeg" time="1 hour ago">

<a href="profiles/michael">Michael</a> needed an extra large cup of coffee.

</activity-card>

<activity-card iconSrc="../img/hendrick.jpeg" time="Yesterday">

<a href="profiles/hendrick">Hendrick</a> watched a movie.

</activity-card>

</div>

</body>

</html>
<!DOCTYPE html>

<html>

<head lang="en">

<meta charset="UTF-8">

<title>Activity Stream - Standard Web Component</title>

<link href="stylesheet.css" rel="stylesheet">

<script src="bower_components/jquery/dist/jquery.min.js"></script>

</head>

<body>

<template>

<style>

* {

font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;

}

.activity {

width: 500px;

height: 40px;

padding: 10px;

background-color: #f0f8ff;

font-size: small;

margin: 10px 0;

}

.activity .icon {

float: left;

border-radius: 100%;

}



.activity .time {

float: right;

color: #b7b7b7;

font-style: italic;

}

.activity .content {

margin-left: 60px;

}

</style>



<div class="activity">

<img class="icon" src="" width="40" height="40">

<div class="time"></div>

<div class="content"><content></content></div>

</div>

</template>





<script>



var activityPrototype = Object.create(HTMLElement.prototype);



activityPrototype.createdCallback = function() {

var template = document.querySelector('template');

var clone = document.importNode(template.content, true);



var host = $(this);

$(".icon", clone).attr("src", host.attr("iconSrc"));

$(".time", clone).text(host.attr("time"));



var shadowRoot = this.createShadowRoot();

shadowRoot.appendChild(clone);

};



// Register our new element

document.registerElement('activity-card', {

prototype: activityPrototype

});

</script>



<div class="activity-stream">

<h2>Activities</h2>

<activity-card iconSrc="../img/michael.jpeg" time="Seconds ago">

<a href="profiles/michael">Michael</a> had fun writing web components.

</activity-card>

<activity-card iconSrc="../img/hendrick.jpeg" time="Minutes ago">

<a href="profiles/hendrick">Hendrick</a> blogged on <a href="http://guigarage.com">GuiGarage</a>.

</activity-card>

<activity-card iconSrc="../img/michael.jpeg" time="1 hour ago">

<a href="profiles/michael">Michael</a> needed an extra large cup of coffee.

</activity-card>

<activity-card iconSrc="../img/hendrick.jpeg" time="Yesterday">

<a href="profiles/hendrick">Hendrick</a> watched a movie.

</activity-card>

</div>

</body>

</html>
Component Code
Application Code
Application Code
Component Code
Application Code
Application Code
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Html Import
<!DOCTYPE html>

<html>

<head lang="en">

<meta charset="UTF-8">

<title>Activity Stream - Standard Web Component</title>

<link href="stylesheet.css" rel="stylesheet">

<script src="bower_components/jquery/dist/jquery.min.js"></script>

</head>

<body>

<div class="activity-stream">

<h2>Activities</h2>

<activity-card iconSrc="../img/michael.jpeg" time="Seconds ago">

<a href="profiles/michael">Michael</a> had fun writing web components.

</activity-card>

<activity-card iconSrc="../img/hendrick.jpeg" time="Minutes ago">

<a href="profiles/hendrick">Hendrick</a> blogged on <a href="http://guigarage.com">GuiGarage</a>.

</activity-card>

<activity-card iconSrc="../img/michael.jpeg" time="1 hour ago">

<a href="profiles/michael">Michael</a> needed an extra large cup of coffee.

</activity-card>

<activity-card iconSrc="../img/hendrick.jpeg" time="Yesterday">

<a href="profiles/hendrick">Hendrick</a> watched a movie.

</activity-card>

</div>

</body>

</html>
<template>

<style>

* {

font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;

}

.activity {

width: 500px;

height: 40px;

padding: 10px;

background-color: #f0f8ff;

font-size: small;

margin: 10px 0;

}

.activity .icon {

float: left;

border-radius: 100%;

}



.activity .time {

float: right;

color: #b7b7b7;

font-style: italic;

}

.activity .content {

margin-left: 60px;

}

</style>



<div class="activity">

<img class="icon" src="" width="40" height="40">

<div class="time"></div>

<div class="content"><content></content></div>

</div>

</template>





<script>



var activityPrototype = Object.create(HTMLElement.prototype);



activityPrototype.createdCallback = function() {

var template = document.querySelector('template');

var clone = document.importNode(template.content, true);



var host = $(this);

$(".icon", clone).attr("src", host.attr("iconSrc"));

$(".time", clone).text(host.attr("time"));



var shadowRoot = this.createShadowRoot();

shadowRoot.appendChild(clone);

};



// Register our new element

document.registerElement('activity-card', {

prototype: activityPrototype

});

</script>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Html Import
<!DOCTYPE html>

<html>

<head lang="en">

<meta charset="UTF-8">

<title>Activity Stream - Standard Web Component</title>

<link href="stylesheet.css" rel="stylesheet">

<script src="bower_components/jquery/dist/jquery.min.js"></script>

</head>

<body>

<div class="activity-stream">

<h2>Activities</h2>

<activity-card iconSrc="../img/michael.jpeg" time="Seconds ago">

<a href="profiles/michael">Michael</a> had fun writing web components.

</activity-card>

<activity-card iconSrc="../img/hendrick.jpeg" time="Minutes ago">

<a href="profiles/hendrick">Hendrick</a> blogged on <a href="http://guigarage.com">GuiGarage</a>.

</activity-card>

<activity-card iconSrc="../img/michael.jpeg" time="1 hour ago">

<a href="profiles/michael">Michael</a> needed an extra large cup of coffee.

</activity-card>

<activity-card iconSrc="../img/hendrick.jpeg" time="Yesterday">

<a href="profiles/hendrick">Hendrick</a> watched a movie.

</activity-card>

</div>

</body>

</html>
<template>

<style>

* {

font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;

}

.activity {

width: 500px;

height: 40px;

padding: 10px;

background-color: #f0f8ff;

font-size: small;

margin: 10px 0;

}

.activity .icon {

float: left;

border-radius: 100%;

}



.activity .time {

float: right;

color: #b7b7b7;

font-style: italic;

}

.activity .content {

margin-left: 60px;

}

</style>



<div class="activity">

<img class="icon" src="" width="40" height="40">

<div class="time"></div>

<div class="content"><content></content></div>

</div>

</template>





<script>



var activityPrototype = Object.create(HTMLElement.prototype);



activityPrototype.createdCallback = function() {

var template = document.querySelector('template');

var clone = document.importNode(template.content, true);



var host = $(this);

$(".icon", clone).attr("src", host.attr("iconSrc"));

$(".time", clone).text(host.attr("time"));



var shadowRoot = this.createShadowRoot();

shadowRoot.appendChild(clone);

};



// Register our new element

document.registerElement('activity-card', {

prototype: activityPrototype

});

</script>
activity-card.html
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Html Import
<!DOCTYPE html>

<html>

<head lang="en">

<meta charset="UTF-8">

<title>Activity Stream - Standard Web Component</title>

<link href="stylesheet.css" rel="stylesheet">

<script src="bower_components/jquery/dist/jquery.min.js"></script>

</head>

<body>

<div class="activity-stream">

<h2>Activities</h2>

<activity-card iconSrc="../img/michael.jpeg" time="Seconds ago">

<a href="profiles/michael">Michael</a> had fun writing web components.

</activity-card>

<activity-card iconSrc="../img/hendrick.jpeg" time="Minutes ago">

<a href="profiles/hendrick">Hendrick</a> blogged on <a href="http://guigarage.com">GuiGarage</a>.

</activity-card>

<activity-card iconSrc="../img/michael.jpeg" time="1 hour ago">

<a href="profiles/michael">Michael</a> needed an extra large cup of coffee.

</activity-card>

<activity-card iconSrc="../img/hendrick.jpeg" time="Yesterday">

<a href="profiles/hendrick">Hendrick</a> watched a movie.

</activity-card>

</div>

</body>

</html>
<template>

<style>

* {

font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;

}

.activity {

width: 500px;

height: 40px;

padding: 10px;

background-color: #f0f8ff;

font-size: small;

margin: 10px 0;

}

.activity .icon {

float: left;

border-radius: 100%;

}



.activity .time {

float: right;

color: #b7b7b7;

font-style: italic;

}

.activity .content {

margin-left: 60px;

}

</style>



<div class="activity">

<img class="icon" src="" width="40" height="40">

<div class="time"></div>

<div class="content"><content></content></div>

</div>

</template>





<script>



var activityPrototype = Object.create(HTMLElement.prototype);



activityPrototype.createdCallback = function() {

var template = document.querySelector('template');

var clone = document.importNode(template.content, true);



var host = $(this);

$(".icon", clone).attr("src", host.attr("iconSrc"));

$(".time", clone).text(host.attr("time"));



var shadowRoot = this.createShadowRoot();

shadowRoot.appendChild(clone);

};



// Register our new element

document.registerElement('activity-card', {

prototype: activityPrototype

});

</script>
activity-card.html
<link rel="import" href="activity-card.html">
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Html Import
36+ and
Android Browser
37
26+
Use Web
Components today
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
webcomponent.js
• Today not all browsers support the new standards
• The community provides a pollyfills to enable web
components in browser that have no native support
$ bower install --save webcomponentsjs
<script src="bower_components/webcomponentsjs/webcomponents.js"></script>
install it with bower
use it in your code
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
webcomponent.js
• The polyfills are the junction of X-Tag and
Polymer basic libraries
• Mozilla created X-Tag as a polyfill to provide
web components
• Google created Polymer as a polyfill to
provide web components
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
webcomponent.js
• X-Tag and Polymer depends on
webcomponents-js
• Both libraries provide additional
features that are not part of the
specification
webcomponents.org
Polymer
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Polymer
• Adds sugar on top of web components
• Easy to use
• Extendable
• Polymer is created & supported by
Google
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Polymer
• Separated in several parts:
• Polymer API
• Iron Elements
• Paper Elements
• …
www.polymer-project.org
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Polymer
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Iron Elements
• Iron Elements are low level components
• Most Paper UI components base on Iron
• Icons, layouts …
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Icons
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Icons
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Google Web Components
• Google is building a lot of components
(maps, youtube…)
<google-chart></google-chart>
<google-hangout-button></google-hangout-button>
Paper Elements
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Polymer Paper
• Complete component library based on
Material Design
Bower
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Bower
• A package manager for the web
• Search for dependencies and install
them as packages
• Created by Twitter
• Open Source
www.bower.io
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Bower
requires npm, node.js and git
$ npm install -g bower
$ bower init
$ bower install --save webcomponentsjs
in your project folder
download &
add module
add dependency to
bower file
Polymer Paper
Components
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
How to use Components
• All components are build as web components
• A single component or a set can be added by
using bower
$ bower install --save Polymer/paper-slider
<link rel="import" href="bower_components/paper-slider/paper-slider.html">
import it in HTML
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Paper Button
• The default Button
• shows ripple animation on click
<paper-button>flat button</paper-button>
<paper-button raised>raised button</paper-button>
<paper-button noink>No ripple effect</paper-button>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Paper CheckBox
• A styled CheckBox
• State can be defined as attribute
<paper-checkbox></paper-checkbox>
<paper-checkbox checked></paper-checkbox>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Paper Dialog
• A dialog
• Supports title, modality, actions, …
<paper-dialog heading="Title">
<p>Some content</p>
</paper-dialog>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Overview
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Overview
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Layout
• HeaderPanel
• Toolbar
• DrawerPanel
• Scaffold
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Toolbar
• An application toolbar
• Toolbar content will be aligned
<core-toolbar>
<paper-icon-button icon="menu"></paper-icon-button>
<div>My Application</div>
<span flex></span>
<paper-icon-button icon="event"></paper-icon-button>
</core-toolbar>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
HeaderPanel
• Wrapper around toolbar and content
• Toolbar always on top
• Content scrollable
<core-header-panel flex>
<core-toolbar>Title</core-toolbar>
<div>content</div>
</core-header-panel>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
DrawerPanel
• Adds a responsive menu
• Defines attributes to
open and close the
menu
• Normally wraps 2 core-
header-panel
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
DrawerPanel
<core-drawer-panel>
<core-header-panel drawer>
<core-toolbar></core-toolbar>
<core-menu>
<core-item label="One"></core-item>
</core-menu>
</core-header-panel>
<core-header-panel main>
<core-toolbar>
<paper-icon-button core-drawer-toggle icon="menu"></paper-icon-button>
</core-toolbar>
<div>content</div>
</core-header-panel>
</core-drawer-panel>
drawer panel
main panel
show drawer
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Scaffold
• Basic skeleton
• Best practice to
create an
application
• Contains all the
shown features
<core-scaffold>
<core-header-panel navigation flex>
<!-- nav drawer -->
</core-header-panel>
<span tool>Title</span>
<div>content</div>
</core-scaffold>
defines the drawer
defines the main
toolbar
using Paper
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Paper Demo
• Create a new folder
• Install needed modules with Bower
$ mkdir app
$ cd app
$ bower init
$ bower install --save PolymerElements/paper-elements
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Paper Demo
• Create index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body>Hello World</body>
</html>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Paper Demo
• add webcomponents.js
• 
<head>
. . .
<script src=„bower_components/webcomponentsjs/webcomponents.js">
</script>
</head>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Paper Demo
• add Roboto Font
• 
<head>
<link rel="import" href=„bower_components/font-roboto/
roboto.html">
<style>
html,body {
font-family: 'RobotoDraft', sans-serif;
}
</style>
</head>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Paper Demo
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Paper Demo
• add a header panel with a toolbar
<body class="fullbleed layout vertical">

<paper-header-panel class="flex">

<paper-toolbar>Title</paper-toolbar>

</paper-header-panel>

</body>

<link rel=„import" href="bower_components/paper-styles/paper-styles.html">
<link rel=„import" href="bower_components/paper-header-panel/paper-header-panel.html">
<link rel="import" href="bower_components/paper-toolbar/paper-toolbar.html">
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Paper Demo
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Paper Demo
• Add some content to the toolbar
<link rel=„import" href="bower_components/iron-icons/iron-icons.html">
<link rel="import" href="bower_components/paper-icon-button/paper-icon-button.html">
<paper-toolbar>

<paper-icon-button icon="menu"></paper-icon-button>

<span class="flex">Title</span>

<paper-icon-button icon="add"></paper-icon-button>

<paper-icon-button icon="remove"></paper-icon-button>

</paper-toolbar>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Paper Demo
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Paper Demo
• Add paper elements as content
<link rel="import"
href=„bower_components/paper-input/paper-input.html">
<link rel="import"
href="bower_components/paper-button/paper-button.html">
<div class="layout vertical">
<paper-input label="Name"></paper-input>
<paper-input label="Description"></paper-input>
<paper-button raised>save</paper-button>
</div>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Paper Demo
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Paper Demo
• Add some padding
.content {
padding: 20px;
}
<div class="content layout vertical">
<paper-input label="Name"></paper-input>
<paper-input label="Description"></paper-input>
<paper-button raised>save</paper-button>
</div>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Paper Demo
www.guigarage.com
Custom
Components
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Custom Components
• Polymer can be used to create custom
web components
• Defines a nice and modern API to create
components
• Adds several features on top of the spec
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
A First Example
<link rel=„import" href="bower_components/polymer/polymer.html">
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
A First Example
<link rel=„import" href="bower_components/polymer/polymer.html">
<dom-module id="dom-element">
</dom-module>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
A First Example
<link rel=„import" href="bower_components/polymer/polymer.html">
<dom-module id="dom-element">
<template>
<p>I'm a DOM element. This is my local DOM!</p>
</template>
</dom-module>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
A First Example
<link rel=„import" href="bower_components/polymer/polymer.html">
<dom-module id="dom-element">
<template>
<p>I'm a DOM element. This is my local DOM!</p>
</template>
<script>
Polymer({is: "dom-element"});
</script>
</dom-module>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
• Component name must contain a "-"
• Polymer script call must be included
• Template is not needed
• Once it is created it can be used as
custom tag
Custom Components
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Lifecycle
• Polymer defines it’s own lifecycle that is
based on the Web Component Spec
lifecycle
• Callbacks can simply be defined in
Polymer
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Difference to Spec
• created instead of createdCallback
• attached instead of attachedCallback
• detached instead of detachedCallback
• attributeChanged instead of
attributeChangedCallback
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Additional Callback
• Polymer adds an extra callback ready which is
invoked when Polymer has finished creating and
initializing the element’s local DOM.
• The created callback is always called before
ready.
• The ready callback is always called before
attached.
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Example<script>
Polymer({
is: „dom-element“,
ready: function () {
console.log('Ready!');
},
detached: function() {
console.log(this.localName + '#' + this.id + ' was detached');
},
attributeChanged: function(name, type) {
console.log('Attribute ' + name + ' was changed');
}
});
</script>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Property
• Properties can be specified for a
Polymer component
• A property can be of the following types:
• Boolean, Date, Number, String,
Array or Object
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Property
• Properties can be defined in JavaScript
Polymer({
is: 'my-component',
properties: {
user: String,
isHappy: Boolean
}
});
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Property
• Properties can be set in JavaScript







Properties can be set as HTML attribute
ready: function () {
this.set(‘user‘,’unknown‘);
}
<my-component user=‘unknown‘></my-component>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Property
• Default value can be specified
properties: {
user: {
type: String,
value: ‘unknown‘
},
isHappy: Boolean
}
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Data Binding
• binds a property to an attribute of an
element



• Use [[prop]] for one-way-binding
• Property defines if {{prop}} is one-way or
bidirectional binding
<child-element name="{{myName}}"></child-element>
Ok, let’s create
an application
Mockup
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Basic
Layout
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Application Basic Layout
• Header with fixed size

• Resizeable main area

• Footer with fixed size
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Polymer Layout
• The Polymer layout is based on flexbox
• Use Polymer layout classes to simplify
the usage of flexbox
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Flexbox
• New CSS 3 layout
• Flexbox consists of flex containers and
flex items.
box box box
container
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Flexbox
• Contents can be laid out in any flow direction (leftwards,
rightwards, downwards, or even upwards!)
• Contents can be laid out linearly along a single (main) axis
or wrapped into multiple lines along a secondary (cross)
axis
• Contents can “flex” their sizes to respond to the available
space
• …
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Flexbox
box box box
container
flex-direction: row;
box
box
box
container
flex-direction:column;
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Flexbox
box box box
container
flex: 0; flex: 0;flex: 1;
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Application Basic Layout
fix height
fix height
dynamic
height
flexbox
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Using Flex Box in Polymer
• Polymer defines several layout classes
• layout: basic class that must be set
• horizontal: layout content in a row
• vertical: layout content in a column
• flex: content will fill space
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Polymer Layout
Alpha Beta Gamma
<div class="horizontal layout">
<div>Alpha</div>
<div class="flex">Beta (flex)</div>
<div>Gamma</div>
</div>
Application
Structure
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Application Structure
• A Polymer application is based on web
components
• The components define a hierarchy
• chat-view component contains
several chat-bubble components
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Application Structure
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Application Structure
Yeah!
message-view
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
chat-bubble
Application Structure
Yeah!
message-view
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
chat-view
chat-bubble
Application Structure
Yeah!
message-view
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
app-view
chat-view
chat-bubble
Application Structure
Yeah!
message-view
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Like building futuristic Matrjoschkas with Lego
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Application Structure
• The demo will use bower to handle all
dependencies
• Real applications should use a build
script
• like Gulp or Grunt
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
index.html
• add web components polyfill script
• Import basic dependencies like Roboto-
Font and Polymer layouts
• body contains only one web
component: the application
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
imports


<script src="bower_components/webcomponentsjs/webcomponents.js"></script>



<link rel="import" href="bower_components/paper-styles/paper-styles.html">

<link rel="import" href="bower_components/font-roboto/roboto.html">

PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
imports


<script src="bower_components/webcomponentsjs/webcomponents.js"></script>



<link rel="import" href="bower_components/paper-styles/paper-styles.html">

<link rel="import" href="bower_components/font-roboto/roboto.html">

web components polyfill
font and layouts
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
component-xy.html
• Contains the definition of one web
component
• All components that are needed
internally should be imported
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Workspace
bower.json
index.html
chat-bubble.html
chat-view.html
chat-header.html
chat-footer.html
chat-app.html
Chat Bubble
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Chat Bubble
Sender
This is the chat message. The size of the
bubble should fit to this message. Next to
normal text emojis can be part of a
message: 😊
5 min ago
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Chat Bubble
Sender
This is the chat message. The size of the
bubble should fit to this message. Next to
normal text emojis can be part of a
message: 😊
5 min ago
depends on parent width
dependsontextlength
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Chat Bubble
Sender
This is the chat message. The size of the
bubble should fit to this message. Next to
normal text emojis can be part of a
message: 😊
5 min ago
dependsontext
length
fix
fix
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Chat Bubble
Sender
This is the chat message. The size of the
bubble should fit to this message. Next to
normal text emojis can be part of a
message: 😊
5 min ago
fix
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Chat Bubble
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Chat Bubble
<div id="bubble"><div>
#bubble {

background-color: #F2F2F2;

border-radius: 5px;

}
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Chat Bubble
Sender
This is the chat message. The size of the
bubble should fit to this message. Next to
normal text emojis can be part of a
message: 😊
5 min ago
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Chat Bubble
<div id="bubble"><div>
#bubble {

background-color: #F2F2F2;

border-radius: 5px;
padding: 2px 12px 2px 12px;
}
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Chat Bubble
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
CSS ::after Selector
p::after {

content: " - Remember this";

}
• The ::after selector inserts something after
the content of each selected element(s).
• Use the content property to specify the
content to insert.
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Chat Bubble
#bubble::after {

background-color: #F2F2F2;

display: block;

position: absolute;

content: "00a0";

height: 16px;

width: 20px;

bottom: 11px;

transform: rotate(29deg) skew(-35deg);

}
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Chat Bubble Web Component
<dom-module id=„chat-bubble">
<style>
#bubble { . . . }
</style>


<template>
<div id=„bubble"> . . . </div>
</template>


</dom-module>


<script>
Polymer({

is: "chat-bubble"
});
</script>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Chat Bubble Attributes
• Sender & message should be dynamic
• Can be defined as attributes of the
component
• Use Polymer properties
properties: {

text: String,

sender: String

}
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Problem
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
configure Bubble with CSS
#bubble {

. . .

}
• We can specify 2 separate CSS classes:
me and you
.me {
. . .
}
.you {
. . .
}
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
• We can dynamically change the CCS
class in JS code
• Access bubble div in Polymer

• Mutate class list
change Css class
bubbleDiv.classList.remove('me');

bubbleDiv.classList.add('you');
var bubbleDiv = this.$.bubble;
id of the div
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
• Polymer provides observers for
properties



• Observer will be called whenever
property values changes
Property Observer
me: {
type: Boolean,

observer: ‚_senderChanged'
}
_senderChanged: function (newValue, oldValue) {

this.updateStyleClass(newValue);

}
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
• The initial boolean property value
reflects if a HTML attribute is set
use boolean property
<chat-bubble me></chat-bubble>
<chat-bubble></chat-bubble>
„me“ property == true
„me“ property == false
Chat View
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Chat View
• Should contain a list of chat bubbles
• Scrollable
• based on data array (JSON)
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Polymer Iron
• List of low level components
• Define behavior
• Don’t define theme / skin
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
iron-list
• Defines a list that can be scrolled
• Can contain thousands of elements.
Only visible area is rendered
• Define a template for each cell
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
iron-list
<iron-list items="[[data]]" as="item">

<template>

<chat-bubble text=„[[item.message]]" …></chat-bubble>

</template>

</iron-list>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
provide dummy data
<iron-ajax url="data.json" last-response="{{messages}}" auto></iron-ajax>

• Polymer provides Iron Element to load
JSON data
Application
Header
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Centered Text
• The name should be centered
• Layout should not be effected by
other nodes
.centered {

top: 18px;

left: 0;

position:absolute;

width: 100%;

}
.title {

font-size: 22px;

text-align:center;

}
parent of text text
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Rounded Image
• Avatar image should be rounded
.avatar {

width: 64px;

height: 64px;

border-radius: 32px;

border-style: solid;

border-width: 1px;

border-color: lightgrey;

}
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Dynamic content
• Add some Polymer properties





• Use them inline

Properties: {

title: String,

state: String

}
<div class="centered vertical layout">

<div class="title">{{title}}</div>

<div class="subtitle">{{state}}</div>

</div>
Application
Footer
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Custom Textbox
• <input> can be styled with CSS
• Polymer provides a behavior to add
data binding to a normal input
<input is="iron-input" value="{{message::input}}">
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Custom Button
• Call a internal web component function
when the button is clicked
<button on-click="sendMyMessage">send</button>
Polymer({

is: "input-view",

sendMyMessage: function (e) {…}

});
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Polymer events
• Web Components can fire events

• Observer can be added

• Hint: trigger a resize for iron-list when
content changes:

this.fire('message-send', {message: this.message});
<input-view on-message-send="send"></input-view>
this.$.itemsList.fire('resize');
Emoji Support
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
About Emojis
• All emojis are defined by a a unicode
character
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Emojis in HTML
• Most OS provide a font to render emojis
• As long as the browser supports
unicode and your files are encoded in
unicode you can use them
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Parse Emojis
• Cool lib with word - emoji mapping can be
found here: 

github.com/muan/emojilib
• A Polymer Emoji selector can be found here:

github.com/notwaldorf/emoji-selector
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Emojis in the chat
var converted = '';

var words = input.split(' ');

for (var i = 0; i < words.length; i++) {

var emoji = getMeAnEmoji(words[i]);

if(emoji != '') {

converted = converted + ' ' + emoji;

} else {

converted = converted + ' ' + words[i];

}

}
Adding a
server
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Dolphin Platform
• Enterprise Framework with
Presentation Model pattern
• Server centric logic
• Spring and JavaEE integration
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Dolphin Platform
• JavaFX, AngularJS & Google Polymer
client APIs









… More will come
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Dolphin Platform
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Model
• Defined in Java
• Hierarchical models are no problem
• Full observable
• Collection support
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Model
@DolphinBean
public class MyModel {
private Property<String> name;
public Property<String> nameProperty() {return name;}
}
Dolphin Platform propere can be
used on client and server
This is NOT a JFXProperty
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Controller
• Controller is defined on the server
• Will be managed by the container
(Spring, JavaEE, …)
• Full CDI support
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Controller
@DolphinController
public class MyController {
@DolphinModel
private MyModel model;
@PostConstruct
public void init() {
model.nameProperty().onChange(e -> System.out.println(„CHANGE“));
}
}
Inject the model
Use containerfeatures
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
View
• The smallest part ;)
• Use the complete UI Toolkit power
• Simply bind your view to the model
• Trigger controller actions
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
View
<dom-module id="my-view">
<template>
<paper-input label="Task name" value="{{model.name}}"></paper-input>
</template>
</dom-module>
<script>
Polymer({
is: "my-view",
behaviors: [clientContext.createBehavior('MyController')]
});
</script>
Dolphin Platform providesPolymer behavior
Server controller
Dolphin Platformmodel
Chat App
PolymerWeb Components & by
Sending a message
Client Server
PolymerWeb Components & by
Sending a message
Client Server
call DolphinAction
PolymerWeb Components & by
Sending a message
Client Server
Event
Bus
call DolphinAction
PolymerWeb Components & by
Sending a message
Client Server
Event
Bus
call DolphinAction
publish
PolymerWeb Components & by
Sending a message
Client Server
Event
Bus
call DolphinAction
publish
PolymerWeb Components & by
Sending a message
Client Server
Event
Bus
call DolphinAction
publish
notify
PolymerWeb Components & by
Sending a message
Client
Presentation
Model
Server
Event
Bus
call DolphinAction
publish
notify
PolymerWeb Components & by
Sending a message
Client
Presentation
Model
Server
Event
Bus
call DolphinAction
publish
notifyupdate
PolymerWeb Components & by
Sending a message
Client
Presentation
Model
Server
Event
Bus
call DolphinAction
publish
notifyupdate
PolymerWeb Components & by
Sending a message
Client
Presentation
Model
Server
Event
Bus
call DolphinAction
publish
notifyupdate
synced
automatically
PolymerWeb Components & by
client code diff
Additional
Topics
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Additional Topics
• Behaviors
• Animations
• Custom CSS properties
• DOM manipulation
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Additional Topics
• Polymer contains more features
• Explorer the Polymer Catalog

• Read the documentation
https://elements.polymer-project.org
https://www.polymer-project.org/1.0/docs/
Real World
Applications
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Real World
• Todo
Polymer
Starter Kit
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Polymer Starter Kit
• Fully functional mini-application
• Defines application structure
• Contains many useful configurations

(e.g. for gitignore, jshint, travis)
• Sophisticated build script
• Sidenote: all files contain copyright headers
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Polymer Starter Kit
• Minification ( js, css, images)
• Inlining of HTML Imports
• Cache Config for Offline Usage
• Local Server (with browser-sync)
• Testing
Web Component
Tester
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Web Component Tester
npm install -g web-component-tester
wct
Installation
Usage
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Web Component Tester
• Integrates Mocha, Chai, and Sinon
• Runs with Selenium
• Integration with Sauce Labs provided
• By default runs all tests in test/
• Tasks for grunt and gulp available

(though gulp integration is sub-optimal)
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Web Component Tester
<head>

<meta charset="utf-8">

<script src="../bower_components/webcomponentsjs/webcomponents.min.js">
</script>

<script src="/web-component-tester/browser.js"></script>

<link rel="import" href="../chat-bubble.html">

</head>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Web Component Tester
<head>

<meta charset="utf-8">

<script src="../bower_components/webcomponentsjs/webcomponents.min.js">
</script>

<script src="/web-component-tester/browser.js"></script>

<link rel="import" href="../chat-bubble.html">

</head>
web component polyfill
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Web Component Tester
<head>

<meta charset="utf-8">

<script src="../bower_components/webcomponentsjs/webcomponents.min.js">
</script>

<script src="/web-component-tester/browser.js"></script>

<link rel="import" href="../chat-bubble.html">

</head>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Web Component Tester
<head>

<meta charset="utf-8">

<script src="../bower_components/webcomponentsjs/webcomponents.min.js">
</script>

<script src="/web-component-tester/browser.js"></script>

<link rel="import" href="../chat-bubble.html">

</head> provided by wct
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Web Component Tester
<head>

<meta charset="utf-8">

<script src="../bower_components/webcomponentsjs/webcomponents.min.js">
</script>

<script src="/web-component-tester/browser.js"></script>

<link rel="import" href="../chat-bubble.html">

</head>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Web Component Tester
<head>

<meta charset="utf-8">

<script src="../bower_components/webcomponentsjs/webcomponents.min.js">
</script>

<script src="/web-component-tester/browser.js"></script>

<link rel="import" href="../chat-bubble.html">

</head>
component under test
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Web Component Tester
<body>
<test-fixture id="chatBubbleFixture">

<template>

<chat-bubble></chat-bubble>

</template>

</test-fixture>
...
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Web Component Tester
<body>
<test-fixture id="chatBubbleFixture">

<template>

<chat-bubble></chat-bubble>

</template>

</test-fixture>
...
provided by wct
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Web Component Tester
<body>
<test-fixture id="chatBubbleFixture">

<template>

<chat-bubble></chat-bubble>

</template>

</test-fixture>
...
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Web Component Tester
<body>
<test-fixture id="chatBubbleFixture">

<template>

<chat-bubble></chat-bubble>

</template>

</test-fixture>
...
web component under test
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Web Component Tester<script>

describe('<chat-bubble>', function() {

it('should show the sender', function(done) {

var chatBubble = fixture('chatBubbleFixture');

chatBubble.set('sender', 'Test Sender');

setTimeout(function () {

expect(chatBubble.$$('.sender'))
.to.have.property('textContent')

.that.contains('Test Sender');

done();

});

});

});

</script>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Web Component Tester<script>

describe('<chat-bubble>', function() {

it('should show the sender', function(done) {

var chatBubble = fixture('chatBubbleFixture');

chatBubble.set('sender', 'Test Sender');

setTimeout(function () {

expect(chatBubble.$$('.sender'))
.to.have.property('textContent')

.that.contains('Test Sender');

done();

});

});

});

</script>
create component
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Web Component Tester
<script>

describe('<chat-bubble>', function() {

it('should show the sender', function(done) {

var chatBubble = fixture('chatBubbleFixture');

chatBubble.set('sender', 'Test Sender');

setTimeout(function () {

expect(chatBubble.$$('.sender'))
.to.have.property('textContent')

.that.contains('Test Sender');

done();

});

});

});

</script>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Web Component Tester
<script>

describe('<chat-bubble>', function() {

it('should show the sender', function(done) {

var chatBubble = fixture('chatBubbleFixture');

chatBubble.set('sender', 'Test Sender');

setTimeout(function () {

expect(chatBubble.$$('.sender'))
.to.have.property('textContent')

.that.contains('Test Sender');

done();

});

});

});

</script>
set property
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Web Component Tester<script>

describe('<chat-bubble>', function() {

it('should show the sender', function(done) {

var chatBubble = fixture('chatBubbleFixture');

chatBubble.set('sender', 'Test Sender');

setTimeout(function () {

expect(chatBubble.$$('.sender'))
.to.have.property('textContent')

.that.contains('Test Sender');

done();

});

});

});

</script>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Web Component Tester<script>

describe('<chat-bubble>', function() {

it('should show the sender', function(done) {

var chatBubble = fixture('chatBubbleFixture');

chatBubble.set('sender', 'Test Sender');

setTimeout(function () {

expect(chatBubble.$$('.sender'))
.to.have.property('textContent')

.that.contains('Test Sender');

done();

});

});

});

</script>
needs to be
asynchronous
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Web Component Tester<script>

describe('<chat-bubble>', function() {

it('should show the sender', function(done) {

var chatBubble = fixture('chatBubbleFixture');

chatBubble.set('sender', 'Test Sender');

setTimeout(function () {

expect(chatBubble.$$('.sender'))
.to.have.property('textContent')

.that.contains('Test Sender');

done();

});

});

});

</script>
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Web Component Tester<script>

describe('<chat-bubble>', function() {

it('should show the sender', function(done) {

var chatBubble = fixture('chatBubbleFixture');

chatBubble.set('sender', 'Test Sender');

setTimeout(function () {

expect(chatBubble.$$('.sender'))
.to.have.property('textContent')

.that.contains('Test Sender');

done();

});

});

});

</script>
DOM-query
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Web Component Tester
module.exports = {

plugins: {

sauce: {

browsers: [

{

platform: 'Windows 8.1',

browserName: 'internet explorer',

version: '11.0'

}

]

}

}

};
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Web Component Tester
module.exports = {

plugins: {

sauce: {

browsers: [

{

platform: 'Windows 8.1',

browserName: 'internet explorer',

version: '11.0'

}

]

}

}

};
environment
configuration
Create reusable
components
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Situation
• All components are part of our project
• We can’t reuse them in other projects
• The components are not isolated
• Looks like a bad mixup
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
Wish list
• We want reusable components
• A component should be independent and
isolated
• Components can depend on each other /
include other custom components
• Use a component as a bower dependency
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
seed-element
• Blueprint for custom component
• Defines demo, test, and main section
• Web component tester and polyserve
integrated
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
polyserve
• Polymer offers a special web server to
create reusable components
• serves project files under /components/
{bower-name}/
• other component are served from ./
bower_components/
PolymerWeb Components & by
Questions: https://goo.gl/iZI3l0
polyserve
• Your component can refer to external
components like your component is in the
bower_components folder
• Simple to create a github repo for one
specific reusable component
• Polymer Paper is doing the same
Questions?

More Related Content

Viewers also liked

JavaFX JumpStart @JavaOne 2016
JavaFX JumpStart @JavaOne 2016JavaFX JumpStart @JavaOne 2016
JavaFX JumpStart @JavaOne 2016
Hendrik Ebbers
 
Rich Enterprise Applications with JavaFX
Rich Enterprise Applications with JavaFXRich Enterprise Applications with JavaFX
Rich Enterprise Applications with JavaFX
Max Katz
 
JavaFX Enterprise
JavaFX EnterpriseJavaFX Enterprise
JavaFX Enterprise
Hendrik Ebbers
 
JavaFX Enterprise (JavaOne 2014)
JavaFX Enterprise (JavaOne 2014)JavaFX Enterprise (JavaOne 2014)
JavaFX Enterprise (JavaOne 2014)
Hendrik Ebbers
 
DataFX 8 (JavaOne 2014)
DataFX 8 (JavaOne 2014)DataFX 8 (JavaOne 2014)
DataFX 8 (JavaOne 2014)
Hendrik Ebbers
 
JavaFX 2 Rich Desktop Platform
JavaFX 2 Rich Desktop PlatformJavaFX 2 Rich Desktop Platform
JavaFX 2 Rich Desktop Platform
Rajmahendra Hegde
 

Viewers also liked (6)

JavaFX JumpStart @JavaOne 2016
JavaFX JumpStart @JavaOne 2016JavaFX JumpStart @JavaOne 2016
JavaFX JumpStart @JavaOne 2016
 
Rich Enterprise Applications with JavaFX
Rich Enterprise Applications with JavaFXRich Enterprise Applications with JavaFX
Rich Enterprise Applications with JavaFX
 
JavaFX Enterprise
JavaFX EnterpriseJavaFX Enterprise
JavaFX Enterprise
 
JavaFX Enterprise (JavaOne 2014)
JavaFX Enterprise (JavaOne 2014)JavaFX Enterprise (JavaOne 2014)
JavaFX Enterprise (JavaOne 2014)
 
DataFX 8 (JavaOne 2014)
DataFX 8 (JavaOne 2014)DataFX 8 (JavaOne 2014)
DataFX 8 (JavaOne 2014)
 
JavaFX 2 Rich Desktop Platform
JavaFX 2 Rich Desktop PlatformJavaFX 2 Rich Desktop Platform
JavaFX 2 Rich Desktop Platform
 

Similar to BUILDING MODERN WEB UIS WITH WEB COMPONENTS @ Devoxx

webcomponents (Jfokus 2015)
webcomponents (Jfokus 2015)webcomponents (Jfokus 2015)
webcomponents (Jfokus 2015)
Hendrik Ebbers
 
Introduction to Web Components & Polymer Workshop - JS Interactive
Introduction to Web Components & Polymer Workshop - JS InteractiveIntroduction to Web Components & Polymer Workshop - JS Interactive
Introduction to Web Components & Polymer Workshop - JS Interactive
John Riviello
 
jhipster-geekle-gbloch
jhipster-geekle-gblochjhipster-geekle-gbloch
jhipster-geekle-gbloch
Gaëtan Bloch
 
WebGL Awesomeness
WebGL AwesomenessWebGL Awesomeness
WebGL Awesomeness
Stephan Seidt
 
Introduction to Web Components & Polymer Workshop - U of I WebCon
Introduction to Web Components & Polymer Workshop - U of I WebConIntroduction to Web Components & Polymer Workshop - U of I WebCon
Introduction to Web Components & Polymer Workshop - U of I WebCon
John Riviello
 
JHipster presentation by Gaetan Bloch
JHipster presentation by Gaetan BlochJHipster presentation by Gaetan Bloch
JHipster presentation by Gaetan Bloch
Gaëtan Bloch
 
Workshop: Introduction to Web Components & Polymer
Workshop: Introduction to Web Components & Polymer Workshop: Introduction to Web Components & Polymer
Workshop: Introduction to Web Components & Polymer
John Riviello
 
2015 nouveaux outilsdevweb
2015 nouveaux outilsdevweb2015 nouveaux outilsdevweb
2015 nouveaux outilsdevweb
Philippe Antoine
 
HTML5 development in 30 minutes
HTML5 development in 30 minutesHTML5 development in 30 minutes
HTML5 development in 30 minutes
Nazrul Kamaruddin
 
AngularJS
AngularJSAngularJS
Polymerizando la web
Polymerizando la webPolymerizando la web
Polymerizando la web
Software Guru
 
Inextrix Working Portfolio
Inextrix Working PortfolioInextrix Working Portfolio
Inextrix Working Portfolio
jemsinextrix
 
Inextrix Presentation
Inextrix PresentationInextrix Presentation
Inextrix Presentation
Ruben Stuart
 
Typescript 102 angular and type script
Typescript 102   angular and type scriptTypescript 102   angular and type script
Typescript 102 angular and type script
Bob German
 
64c7d81c-2398-4c8d-a21d-421f53f03deb-160413212748
64c7d81c-2398-4c8d-a21d-421f53f03deb-16041321274864c7d81c-2398-4c8d-a21d-421f53f03deb-160413212748
64c7d81c-2398-4c8d-a21d-421f53f03deb-160413212748
Latha Gummadi
 
Web Components: The Future of Web Development is Here
Web Components: The Future of Web Development is HereWeb Components: The Future of Web Development is Here
Web Components: The Future of Web Development is Here
John Riviello
 
Custom Elements with Polymer Web Components #econfpsu16
Custom Elements with Polymer Web Components #econfpsu16Custom Elements with Polymer Web Components #econfpsu16
Custom Elements with Polymer Web Components #econfpsu16
John Riviello
 
20 tips for website performance
20 tips for website performance20 tips for website performance
20 tips for website performance
Andrew Siemer
 
Forge - DevCon 2016: Collaborative VR using Google Cardboard & the View & Dat...
Forge - DevCon 2016: Collaborative VR using Google Cardboard & the View & Dat...Forge - DevCon 2016: Collaborative VR using Google Cardboard & the View & Dat...
Forge - DevCon 2016: Collaborative VR using Google Cardboard & the View & Dat...
Autodesk
 
Web Components & Polymer 1.0 (Webinale Berlin)
Web Components & Polymer 1.0 (Webinale Berlin)Web Components & Polymer 1.0 (Webinale Berlin)
Web Components & Polymer 1.0 (Webinale Berlin)
Hendrik Ebbers
 

Similar to BUILDING MODERN WEB UIS WITH WEB COMPONENTS @ Devoxx (20)

webcomponents (Jfokus 2015)
webcomponents (Jfokus 2015)webcomponents (Jfokus 2015)
webcomponents (Jfokus 2015)
 
Introduction to Web Components & Polymer Workshop - JS Interactive
Introduction to Web Components & Polymer Workshop - JS InteractiveIntroduction to Web Components & Polymer Workshop - JS Interactive
Introduction to Web Components & Polymer Workshop - JS Interactive
 
jhipster-geekle-gbloch
jhipster-geekle-gblochjhipster-geekle-gbloch
jhipster-geekle-gbloch
 
WebGL Awesomeness
WebGL AwesomenessWebGL Awesomeness
WebGL Awesomeness
 
Introduction to Web Components & Polymer Workshop - U of I WebCon
Introduction to Web Components & Polymer Workshop - U of I WebConIntroduction to Web Components & Polymer Workshop - U of I WebCon
Introduction to Web Components & Polymer Workshop - U of I WebCon
 
JHipster presentation by Gaetan Bloch
JHipster presentation by Gaetan BlochJHipster presentation by Gaetan Bloch
JHipster presentation by Gaetan Bloch
 
Workshop: Introduction to Web Components & Polymer
Workshop: Introduction to Web Components & Polymer Workshop: Introduction to Web Components & Polymer
Workshop: Introduction to Web Components & Polymer
 
2015 nouveaux outilsdevweb
2015 nouveaux outilsdevweb2015 nouveaux outilsdevweb
2015 nouveaux outilsdevweb
 
HTML5 development in 30 minutes
HTML5 development in 30 minutesHTML5 development in 30 minutes
HTML5 development in 30 minutes
 
AngularJS
AngularJSAngularJS
AngularJS
 
Polymerizando la web
Polymerizando la webPolymerizando la web
Polymerizando la web
 
Inextrix Working Portfolio
Inextrix Working PortfolioInextrix Working Portfolio
Inextrix Working Portfolio
 
Inextrix Presentation
Inextrix PresentationInextrix Presentation
Inextrix Presentation
 
Typescript 102 angular and type script
Typescript 102   angular and type scriptTypescript 102   angular and type script
Typescript 102 angular and type script
 
64c7d81c-2398-4c8d-a21d-421f53f03deb-160413212748
64c7d81c-2398-4c8d-a21d-421f53f03deb-16041321274864c7d81c-2398-4c8d-a21d-421f53f03deb-160413212748
64c7d81c-2398-4c8d-a21d-421f53f03deb-160413212748
 
Web Components: The Future of Web Development is Here
Web Components: The Future of Web Development is HereWeb Components: The Future of Web Development is Here
Web Components: The Future of Web Development is Here
 
Custom Elements with Polymer Web Components #econfpsu16
Custom Elements with Polymer Web Components #econfpsu16Custom Elements with Polymer Web Components #econfpsu16
Custom Elements with Polymer Web Components #econfpsu16
 
20 tips for website performance
20 tips for website performance20 tips for website performance
20 tips for website performance
 
Forge - DevCon 2016: Collaborative VR using Google Cardboard & the View & Dat...
Forge - DevCon 2016: Collaborative VR using Google Cardboard & the View & Dat...Forge - DevCon 2016: Collaborative VR using Google Cardboard & the View & Dat...
Forge - DevCon 2016: Collaborative VR using Google Cardboard & the View & Dat...
 
Web Components & Polymer 1.0 (Webinale Berlin)
Web Components & Polymer 1.0 (Webinale Berlin)Web Components & Polymer 1.0 (Webinale Berlin)
Web Components & Polymer 1.0 (Webinale Berlin)
 

More from Hendrik Ebbers

Java Desktop 2019
Java Desktop 2019Java Desktop 2019
Java Desktop 2019
Hendrik Ebbers
 
Java APIs- The missing manual (concurrency)
Java APIs- The missing manual (concurrency)Java APIs- The missing manual (concurrency)
Java APIs- The missing manual (concurrency)
Hendrik Ebbers
 
Beauty & the Beast - Java VS TypeScript
Beauty & the Beast - Java VS TypeScriptBeauty & the Beast - Java VS TypeScript
Beauty & the Beast - Java VS TypeScript
Hendrik Ebbers
 
Java 11 OMG
Java 11 OMGJava 11 OMG
Java 11 OMG
Hendrik Ebbers
 
Java APIs - the missing manual
Java APIs - the missing manualJava APIs - the missing manual
Java APIs - the missing manual
Hendrik Ebbers
 
Multidevice Controls: A Different Approach to UX
Multidevice Controls: A Different Approach to UXMultidevice Controls: A Different Approach to UX
Multidevice Controls: A Different Approach to UX
Hendrik Ebbers
 
Java WebStart Is Dead: What Should We Do Now?
Java WebStart Is Dead: What Should We Do Now?Java WebStart Is Dead: What Should We Do Now?
Java WebStart Is Dead: What Should We Do Now?
Hendrik Ebbers
 
Java ap is you should know
Java ap is you should knowJava ap is you should know
Java ap is you should know
Hendrik Ebbers
 
Test Driven Development with JavaFX
Test Driven Development with JavaFXTest Driven Development with JavaFX
Test Driven Development with JavaFX
Hendrik Ebbers
 
Feature driven development
Feature driven developmentFeature driven development
Feature driven development
Hendrik Ebbers
 
Extreme Gui Makeover
Extreme Gui MakeoverExtreme Gui Makeover
Extreme Gui Makeover
Hendrik Ebbers
 
Bonjour for Java
Bonjour for JavaBonjour for Java
Bonjour for Java
Hendrik Ebbers
 
DataFX - JavaOne 2013
DataFX - JavaOne 2013DataFX - JavaOne 2013
DataFX - JavaOne 2013
Hendrik Ebbers
 
Vagrant Binding JayDay 2013
Vagrant Binding JayDay 2013Vagrant Binding JayDay 2013
Vagrant Binding JayDay 2013
Hendrik Ebbers
 
Devoxx UK 2013: Sandboxing with the Vagrant-Binding API
Devoxx UK 2013: Sandboxing with the Vagrant-Binding APIDevoxx UK 2013: Sandboxing with the Vagrant-Binding API
Devoxx UK 2013: Sandboxing with the Vagrant-Binding API
Hendrik Ebbers
 
Vagrant-Binding JUG Dortmund
Vagrant-Binding JUG DortmundVagrant-Binding JUG Dortmund
Vagrant-Binding JUG Dortmund
Hendrik Ebbers
 
Lightweight and reproducible environments with vagrant and Puppet
Lightweight and reproducible environments with vagrant and PuppetLightweight and reproducible environments with vagrant and Puppet
Lightweight and reproducible environments with vagrant and Puppet
Hendrik Ebbers
 
Jgrid
JgridJgrid

More from Hendrik Ebbers (18)

Java Desktop 2019
Java Desktop 2019Java Desktop 2019
Java Desktop 2019
 
Java APIs- The missing manual (concurrency)
Java APIs- The missing manual (concurrency)Java APIs- The missing manual (concurrency)
Java APIs- The missing manual (concurrency)
 
Beauty & the Beast - Java VS TypeScript
Beauty & the Beast - Java VS TypeScriptBeauty & the Beast - Java VS TypeScript
Beauty & the Beast - Java VS TypeScript
 
Java 11 OMG
Java 11 OMGJava 11 OMG
Java 11 OMG
 
Java APIs - the missing manual
Java APIs - the missing manualJava APIs - the missing manual
Java APIs - the missing manual
 
Multidevice Controls: A Different Approach to UX
Multidevice Controls: A Different Approach to UXMultidevice Controls: A Different Approach to UX
Multidevice Controls: A Different Approach to UX
 
Java WebStart Is Dead: What Should We Do Now?
Java WebStart Is Dead: What Should We Do Now?Java WebStart Is Dead: What Should We Do Now?
Java WebStart Is Dead: What Should We Do Now?
 
Java ap is you should know
Java ap is you should knowJava ap is you should know
Java ap is you should know
 
Test Driven Development with JavaFX
Test Driven Development with JavaFXTest Driven Development with JavaFX
Test Driven Development with JavaFX
 
Feature driven development
Feature driven developmentFeature driven development
Feature driven development
 
Extreme Gui Makeover
Extreme Gui MakeoverExtreme Gui Makeover
Extreme Gui Makeover
 
Bonjour for Java
Bonjour for JavaBonjour for Java
Bonjour for Java
 
DataFX - JavaOne 2013
DataFX - JavaOne 2013DataFX - JavaOne 2013
DataFX - JavaOne 2013
 
Vagrant Binding JayDay 2013
Vagrant Binding JayDay 2013Vagrant Binding JayDay 2013
Vagrant Binding JayDay 2013
 
Devoxx UK 2013: Sandboxing with the Vagrant-Binding API
Devoxx UK 2013: Sandboxing with the Vagrant-Binding APIDevoxx UK 2013: Sandboxing with the Vagrant-Binding API
Devoxx UK 2013: Sandboxing with the Vagrant-Binding API
 
Vagrant-Binding JUG Dortmund
Vagrant-Binding JUG DortmundVagrant-Binding JUG Dortmund
Vagrant-Binding JUG Dortmund
 
Lightweight and reproducible environments with vagrant and Puppet
Lightweight and reproducible environments with vagrant and PuppetLightweight and reproducible environments with vagrant and Puppet
Lightweight and reproducible environments with vagrant and Puppet
 
Jgrid
JgridJgrid
Jgrid
 

Recently uploaded

How to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For FlutterHow to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For Flutter
Daiki Mogmet Ito
 
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdfUnlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Malak Abu Hammad
 
Presentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of GermanyPresentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of Germany
innovationoecd
 
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
名前 です男
 
20240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 202420240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 2024
Matthew Sinclair
 
How to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptxHow to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptx
danishmna97
 
TrustArc Webinar - 2024 Global Privacy Survey
TrustArc Webinar - 2024 Global Privacy SurveyTrustArc Webinar - 2024 Global Privacy Survey
TrustArc Webinar - 2024 Global Privacy Survey
TrustArc
 
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
Neo4j
 
UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5
DianaGray10
 
“I’m still / I’m still / Chaining from the Block”
“I’m still / I’m still / Chaining from the Block”“I’m still / I’m still / Chaining from the Block”
“I’m still / I’m still / Chaining from the Block”
Claudio Di Ciccio
 
GenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizationsGenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizations
kumardaparthi1024
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Paige Cruz
 
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
Edge AI and Vision Alliance
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
mikeeftimakis1
 
20240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 202420240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 2024
Matthew Sinclair
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
Neo4j
 
Serial Arm Control in Real Time Presentation
Serial Arm Control in Real Time PresentationSerial Arm Control in Real Time Presentation
Serial Arm Control in Real Time Presentation
tolgahangng
 
Programming Foundation Models with DSPy - Meetup Slides
Programming Foundation Models with DSPy - Meetup SlidesProgramming Foundation Models with DSPy - Meetup Slides
Programming Foundation Models with DSPy - Meetup Slides
Zilliz
 
Artificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopmentArtificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopment
Octavian Nadolu
 
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
Neo4j
 

Recently uploaded (20)

How to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For FlutterHow to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For Flutter
 
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdfUnlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
 
Presentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of GermanyPresentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of Germany
 
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
 
20240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 202420240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 2024
 
How to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptxHow to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptx
 
TrustArc Webinar - 2024 Global Privacy Survey
TrustArc Webinar - 2024 Global Privacy SurveyTrustArc Webinar - 2024 Global Privacy Survey
TrustArc Webinar - 2024 Global Privacy Survey
 
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
 
UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5
 
“I’m still / I’m still / Chaining from the Block”
“I’m still / I’m still / Chaining from the Block”“I’m still / I’m still / Chaining from the Block”
“I’m still / I’m still / Chaining from the Block”
 
GenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizationsGenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizations
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
 
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
 
20240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 202420240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 2024
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
 
Serial Arm Control in Real Time Presentation
Serial Arm Control in Real Time PresentationSerial Arm Control in Real Time Presentation
Serial Arm Control in Real Time Presentation
 
Programming Foundation Models with DSPy - Meetup Slides
Programming Foundation Models with DSPy - Meetup SlidesProgramming Foundation Models with DSPy - Meetup Slides
Programming Foundation Models with DSPy - Meetup Slides
 
Artificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopmentArtificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopment
 
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
 

BUILDING MODERN WEB UIS WITH WEB COMPONENTS @ Devoxx

  • 2. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 • Lead of JUG Dortmund • Speaker, blogger & author • Java Architect @ Canoo Engineering AG • JavaOne Rockstar • JSR Expert Group member www.guigarage.com@hendrikEbbers Hendrik Ebbers
  • 3. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 • UI magician • Active speaker and writer • Code Monkey @ Canoo Engineering AG • http://blog.netopyr.com @net0pyr Michael Heinrichs
  • 4. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Questions? https://app.sli.do/event/xfb1afkm/ask
  • 5. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Web Component Spec Polymer A first app Real World Applications Content
  • 6.
  • 7.
  • 8. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 frontend code today <li class="yt-shelf-grid-item yt-uix-shelfslider-item">
 <div class="yt-lockup yt-lockup-grid yt-lockup-video vve-check clearfix" data-context-item-id="naiLVvuPCAw"
 data-visibility-tracking= "CFEQpDAYBSITCM7Or_3JucMCFY6yHAodHk0ANiiOHkCMkLzc7-qi1J0B">
 <div class="yt-lockup-dismissable">
 <div class="yt-lockup-thumbnail contains-addto">
 <a aria-hidden="true" href="/watch?v=naiLVvuPCAw" class=" yt-uix-sessionlink spf-link "
 data-sessionlink= "itct=CFEQpDAYBSITCM7Or_3JucMCFY6yHAodHk0ANiiOHjIKZy1oaWdoLXJjaA">
 <div class="yt-thumb video-thumb">
 <img src="//i.ytimg.com/vi/naiLVvuPCAw/mqdefault.jpg" width="196" height="110"/>
 </div>
 Web Applications Today
  • 9. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 frontend code today
  • 10. <li class=" yt-uix-shelfslider-item">
 <div class="yt-lockup yt-lockup-grid yt-lockup-video vve-check clearfix" data-context-item-id="naiLVvuPCAw"
 data-visibility-tracking="CFEQpDAYBSITCM7Or_3JucMCFY6yHAodHk0ANiiOHkCMkLzc7-qi1J0B">
 <div class="yt-lockup-dismissable">
 <div class="yt-lockup-thumbnail contains-addto">
 <a aria-hidden="true" href="/watch?v=naiLVvuPCAw" class=" yt-uix-sessionlink spf-link "
 data-sessionlink="itct=CFEQpDAYBSITCM7Or_3JucMCFY6yHAodHk0ANiiOHjIKZy1oaWdoLXJjaA">
 <div class="yt-thumb video-thumb">
 <img src="//i.ytimg.com/vi/naiLVvuPCAw/mqdefault.jpg" width="196" height="110"/>
 </div>
 <span class="video-time" aria-hidden="true">1:21</span>
 </a>
 <span class="thumb-menu dark-overflow-action-menu video-actions">
 <button onclick=";return false;"
 class="yt-uix-button-reverse flip addto-watch-queue-menu spf-nolink hide-until-delayloaded yt-uix-button yt-uix-button-dark-overflow-action-menu yt-uix-button-size-default yt-uix-button-has-icon no-icon-markup yt-uix-button-empty"
 aria-expanded="false" aria-haspopup="true" type="button">
 <span class="yt-uix-button-arrow yt-sprite"></span>
 <ul class="watch-queue-thumb-menu yt-uix-button-menu yt-uix-button-menu-dark-overflow-action-menu" style="display: none;">
 <li role="menuitem" class="overflow-menu-choice addto-watch-queue-menu-choice addto-watch-queue-play-next yt-uix-button-menu-item"
 data-action="play-next" onclick=";return false;" data-video-ids="naiLVvuPCAw">
 <span class="addto-watch-queue-menu-text">Play next</span>
 </li>
 <li role="menuitem" class="overflow-menu-choice addto-watch-queue-menu-choice addto-watch-queue-play-now yt-uix-button-menu-item"
 data-action="play-now" onclick=";return false;" data-video-ids="naiLVvuPCAw">
 <span class="addto-watch-queue-menu-text">Play now</span>
 </li>
 </ul>
 </button>
 </span>
 <button class="yt-uix-button yt-uix-button-size-small yt-uix-button-default yt-uix-button-empty yt-uix-button-has-icon no-icon-markup addto-button video-actions spf-nolink hide-until-delayloaded addto-watch-later-button-sign-in yt-uix-tooltip"
 type="button" onclick=";return false;" title="Watch Later" role="button"
 data-video-ids="naiLVvuPCAw" data-button-menu-id="shared-addto-watch-later-login"><span
 class="yt-uix-button-arrow yt-sprite"></span></button>
 <button class="yt-uix-button yt-uix-button-size-small yt-uix-button-default yt-uix-button-empty yt-uix-button-has-icon no-icon-markup addto-button addto-queue-button video-actions spf-nolink hide-until-delayloaded addto-tv-queue-button yt-uix- tooltip"
 type="button" onclick=";return false;" title="TV Queue" data-video-ids="naiLVvuPCAw"
 data-style="tv-queue"></button>
 </div>
 <div class="yt-lockup-content">
 <h3 class="yt-lockup-title">
 <a href="/watch?v=naiLVvuPCAw"
 class=" yt-ui-ellipsis yt-ui-ellipsis-2 yt-uix-sessionlink spf-link "
 data-sessionlink="itct=CFEQpDAYBSITCM7Or_3JucMCFY6yHAodHk0ANiiOHjIKZy1oaWdoLXJjaA"
 title="Polizisten hören Helene Fischer&#39;s &#39;Atemlos&#39; im Polizeiauto"
 aria-describedby="description-id-439757"
 dir="ltr">Polizisten hören Helene Fischer&#39;s&#39;Atemlos&#39; im Polizeiauto</a>
 <span class="accessible-description" id="description-id-439757"> - Duration: 1:21.</span>
 </h3>
 <div class="yt-lockup-byline">by <a href="/user/djgreyhair class=" yt-uix-sessionlink spf-link g-hovercard" data-name=""
 data-sessionlink="itct=CFEQpDAYBSITCM7Or_3JucMCFY6yHAodHk0ANiiOHg" data-ytid="UCCBrsuWhYxpwZYSTY7kkB4A">Spass MussSein</a>
 </div>
 <div class="yt-lockup-meta">
 <ul class="yt-lockup-meta-info">
 <li>3,542,577 views</li>
 <li>6 months ago</li>
 </ul>
 </div>
 </div>
 </div>
 </div>
 </li> Web Applications Today
  • 11. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 frontend code tomorrow <shelf title="Popular on YouTube - Switzerland" subscribers=“128,657"> <shelf-grid-item title="iPhone 6 Plus Bend Test" url="https://www.youtube.com/watch?v=znK652H6yQM" thumbnail="https://i.ytimg.com/vi_webp/znK652H6yQM/mqdefault.webp" user="Unbox Therapy" userUrl="https://www.youtube.com/user/unboxtherapy" views="63,732,280" time="4 months ago"> … 
 Web Applications Tomorrow
  • 13. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Web Component Spec • Specified by W3C • Current state of spec can be found online: 
 http://www.w3.org/standards/techs/components#w3c_all
  • 14. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Web Component Spec • Divided in 4 parts: • HTML Templates • Shadow DOM • Custom Elements • HTML Imports
  • 16. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 <template>
  • 17. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 <template> <div class="activity-stream">
 <h2>Activities</h2>
 
 <div class="activity">
 <img class="icon" src="img/hendrik.jpeg" width="40" height="40">
 <div class="time">Minutes ago</div>
 <div class="content"><a>Hendrik</a> did this again.</div>
 </div> 
 … </div> 
 <div class="activity">
 <img class="icon" src="img/michael.jpeg" width="40" height="40">
 <div class="time">Seconds ago</div>
 <div class="content"><a>Michael</a> had fun coding.</div>
 </div>
  • 18. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 <template> <div class="activity-stream">
 <h2>Activities</h2>
 
 <div class="activity">
 <img class="icon" src="img/hendrik.jpeg" width="40" height="40">
 <div class="time">Minutes ago</div>
 <div class="content"><a>Hendrik</a> did this again.</div>
 </div> 
 … </div> 
 <div class="activity">
 <img class="icon" src="img/michael.jpeg" width="40" height="40">
 <div class="time">Seconds ago</div>
 <div class="content"><a>Michael</a> had fun coding.</div>
 </div>
  • 19. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 <template> <div class="activity">
 
 </div> 
 <img class="icon" src="img/michael.jpeg" width="40" height="40">
 <div class="time">Seconds ago</div>
 <div class="content"><a>Michael</a> had fun coding.</div>
  • 20. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 <template> <template id="activity-template">
 </template> <div class="activity">
 
 </div> template tag 
 <img class="icon" src="img/michael.jpeg" width="40" height="40">
 <div class="time">Seconds ago</div>
 <div class="content"><a>Michael</a> had fun coding.</div>
  • 21. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 <template> <div>
 <img class="icon" src="" width="40" height="40">
 <div class="time"></div>
 <div class="content"></div>
 </div> <template id="activity-template">
 </template> <div class="activity">
 
 </div> copy boilerplate template tag 
 <img class="icon" src="img/michael.jpeg" width="40" height="40">
 <div class="time">Seconds ago</div>
 <div class="content"><a>Michael</a> had fun coding.</div>
  • 22. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 <template> <div>
 <img class="icon" src="" width="40" height="40">
 <div class="time"></div>
 <div class="content"></div>
 </div> <template id="activity-template">
 </template> <div class="activity">
 
 </div> copy boilerplate template tag
  • 23. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 <template> <template id="activity-template">
 <div>
 <img class="icon" src="" width="40" height="40">
 <div class="time"></div>
 <div class="content"></div>
 </div>
 </template>
  • 24. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 <template> <template id="activity-template">
 <div>
 <img class="icon" src="" width="40" height="40">
 <div class="time"></div>
 <div class="content"></div>
 </div>
 </template> var template = document.querySelector('#activity-template');
  • 25. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 <template> <template id="activity-template">
 <div>
 <img class="icon" src="" width="40" height="40">
 <div class="time"></div>
 <div class="content"></div>
 </div>
 </template> var template = document.querySelector('#activity-template'); var clone = document.importNode(template.content, true); use content property
  • 26. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 <template> document.body.appendChild(clone); <template id="activity-template">
 <div>
 <img class="icon" src="" width="40" height="40">
 <div class="time"></div>
 <div class="content"></div>
 </div>
 </template> var template = document.querySelector('#activity-template'); var clone = document.importNode(template.content, true); use content property
  • 27. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 <template> <template id="activity-template">
 <div>
 <img class="icon" ng-src="{{item.iconSrc}}" width="40" height="40">
 <div class="time">{{item.time}}</div>
 <div class="content">{{item.content}}</div>
 </div>
 </template>
  • 28. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 <template> <template id="activity-template">
 <div>
 <img class="icon" ng-src="{{item.iconSrc}}" width="40" height="40">
 <div class="time">{{item.time}}</div>
 <div class="content">{{item.content}}</div>
 </div>
 </template> No Data Binding
  • 29. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 <template> 22+ 26+ and Android 4.4+ 7.1+ 15+
  • 31. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Shadow Dom Web Component
  • 32. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Shadow Dom ".content"".content"
  • 33. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Shadow Dom ".content"".content" document.querySelector(".content")
  • 34. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Shadow Dom ".content"".content" document.querySelector(".content")
  • 35. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Shadow Dom ".content"".content" .content { color: blue; } document.querySelector(".content")
  • 36. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Shadow Dom ".content"".content" .content { color: blue; } document.querySelector(".content")
  • 37. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Shadow Dom
  • 38. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Shadow Dom
  • 39. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Shadow Dom Host Root
  • 40. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Shadow Dom visible to
 the user
  • 41. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Shadow Dom visible to
 the user used during rendering
  • 42. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Shadow Dom
  • 43. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Shadow Dom
  • 44. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Shadow Dom document.querySelector(".content") .content { color: blue; } ".content" ".content"
  • 45. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Shadow Dom document.querySelector(".content") .content { color: blue; } ".content" ".content"
  • 46. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Shadow Dom Host
  • 47. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Shadow Dom var root = host.createShadowRoot(); Host
  • 48. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Shadow Dom var root = host.createShadowRoot(); Host Root
  • 49. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Shadow Dom var root = host.createShadowRoot(); Host Root root.appendChild(child1); root.appendChild(child2);
  • 50. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Shadow Dom var root = host.createShadowRoot(); Host Root root.appendChild(child1); root.appendChild(child2);
  • 51. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Shadow Dom Host
  • 52. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Shadow Domvar root = host.createShadowRoot(); Host
  • 53. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Shadow Domvar root = host.createShadowRoot(); Host Root
  • 54. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Shadow Domvar root = host.createShadowRoot(); Host Root var clone = document.importNode( template.content, true);
  • 55. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Shadow Domvar root = host.createShadowRoot(); Host Root var clone = document.importNode( template.content, true); Clone
  • 56. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Shadow Domvar root = host.createShadowRoot(); Host Root var clone = document.importNode( template.content, true); root.appendChild(clone); Clone
  • 57. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Shadow Domvar root = host.createShadowRoot(); Host Root var clone = document.importNode( template.content, true); root.appendChild(clone); Clone
  • 58. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Shadow Dom 25+ and Android 4.4+ 15+
  • 60. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Custom Elements <div class="activity"> <a>Michael</a> had fun coding. </div> How do we store the icon source and time? What is a <div> with the class “activity” anyway?
  • 61. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Custom Elements <div class="activity"> <a>Michael</a> had fun coding. </div>
  • 62. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Custom Elements <activity-card iconSrc="img/michael.jpg" time="Seconds ago"> <a>Michael</a> had fun coding. </activity-card> <div class="activity"> <a>Michael</a> had fun coding. </div>
  • 63. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Custom Elements var activityCardPrototype = Object.create(HTMLElement.prototype);
  • 64. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Custom Elements var activityCardPrototype = Object.create(HTMLElement.prototype); Rough translation to Java class ActivityCard extends HTMLElement {}; Class<ActivityCard> activityCardClass = ActivityCard.class;
  • 65. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Custom Elements var activityCardPrototype = Object.create(HTMLElement.prototype); Rough translation to Java class ActivityCard extends HTMLElement {}; Class<ActivityCard> activityCardClass = ActivityCard.class; var options = {prototype: activityPrototype}
  • 66. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Custom Elements var activityCardPrototype = Object.create(HTMLElement.prototype); Rough translation to Java class ActivityCard extends HTMLElement {}; Class<ActivityCard> activityCardClass = ActivityCard.class; ElementRegistrationOptions options = 
 new ElementRegistrationOptions(activityCardClass); var options = {prototype: activityPrototype}
  • 67. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Custom Elements document.registerElement("activity-card", options); var activityCardPrototype = Object.create(HTMLElement.prototype); Rough translation to Java class ActivityCard extends HTMLElement {}; Class<ActivityCard> activityCardClass = ActivityCard.class; ElementRegistrationOptions options = 
 new ElementRegistrationOptions(activityCardClass); var options = {prototype: activityPrototype}
  • 68. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Custom Elements document.registerElement("activity-card", options); var activityCardPrototype = Object.create(HTMLElement.prototype); document.registerElement("activity-card", options); Rough translation to Java class ActivityCard extends HTMLElement {}; Class<ActivityCard> activityCardClass = ActivityCard.class; ElementRegistrationOptions options = 
 new ElementRegistrationOptions(activityCardClass); var options = {prototype: activityPrototype}
  • 69. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Custom Elements document.registerElement("activity-card", options); var activityCardPrototype = Object.create(HTMLElement.prototype); var options = {prototype: activityPrototype}
  • 70. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Custom Elements document.registerElement("activity-card", options); var activityCardPrototype = Object.create(HTMLElement.prototype); var options = {prototype: activityPrototype} <activity-card iconSrc="img/michael.jpg" time="Seconds ago"> <a>Michael</a> had fun coding. </activity-card>
  • 71. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Custom Elements create attach detach change createdCallback attachedCallback detachedCallback attributeChangedCallback
 (attrName, oldVal, newVal)
  • 72. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Custom Elements
  • 73. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Custom Elementsvar activityPrototype = Object.create(HTMLElement.prototype);
  • 74. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Custom Elementsvar activityPrototype = Object.create(HTMLElement.prototype); activityPrototype.createdCallback = function() {
  • 75. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Custom Elementsvar activityPrototype = Object.create(HTMLElement.prototype); activityPrototype.createdCallback = function() { var template = $("#activity-template");
  • 76. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Custom Elementsvar activityPrototype = Object.create(HTMLElement.prototype); activityPrototype.createdCallback = function() { var template = $("#activity-template"); var clone = document.importNode(template.content, true);
  • 77. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Custom Elementsvar activityPrototype = Object.create(HTMLElement.prototype); activityPrototype.createdCallback = function() { var template = $("#activity-template"); var clone = document.importNode(template.content, true); var host = $(this);
  • 78. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Custom Elementsvar activityPrototype = Object.create(HTMLElement.prototype); activityPrototype.createdCallback = function() { var template = $("#activity-template"); var clone = document.importNode(template.content, true); var host = $(this); $(".icon", clone).attr("src", host.attr("iconSrc"));
  • 79. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Custom Elementsvar activityPrototype = Object.create(HTMLElement.prototype); activityPrototype.createdCallback = function() { var template = $("#activity-template"); var clone = document.importNode(template.content, true); var host = $(this); $(".icon", clone).attr("src", host.attr("iconSrc")); $(".time", clone).text(host.attr("time"));
  • 80. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Custom Elementsvar activityPrototype = Object.create(HTMLElement.prototype); activityPrototype.createdCallback = function() { var template = $("#activity-template"); var clone = document.importNode(template.content, true); var host = $(this); $(".icon", clone).attr("src", host.attr("iconSrc")); $(".time", clone).text(host.attr("time")); var shadow = this.createShadowRoot();
  • 81. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Custom Elementsvar activityPrototype = Object.create(HTMLElement.prototype); activityPrototype.createdCallback = function() { var template = $("#activity-template"); var clone = document.importNode(template.content, true); var host = $(this); $(".icon", clone).attr("src", host.attr("iconSrc")); $(".time", clone).text(host.attr("time")); var shadow = this.createShadowRoot(); shadow.appendChild(clone); };
  • 82. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Custom Elementsvar activityPrototype = Object.create(HTMLElement.prototype); activityPrototype.createdCallback = function() { var template = $("#activity-template"); var clone = document.importNode(template.content, true); var host = $(this); $(".icon", clone).attr("src", host.attr("iconSrc")); $(".time", clone).text(host.attr("time")); var shadow = this.createShadowRoot(); shadow.appendChild(clone); }; document.registerElement("activity-card", {prototype: activityPrototype});
  • 83. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Custom Elements 35+ and Android 4.4.4+ 26+
  • 85. <!DOCTYPE html>
 <html>
 <head lang="en">
 <meta charset="UTF-8">
 <title>Activity Stream - Standard Web Component</title>
 <link href="stylesheet.css" rel="stylesheet">
 <script src="bower_components/jquery/dist/jquery.min.js"></script>
 </head>
 <body>
 <template>
 <style>
 * {
 font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
 }
 .activity {
 width: 500px;
 height: 40px;
 padding: 10px;
 background-color: #f0f8ff;
 font-size: small;
 margin: 10px 0;
 }
 .activity .icon {
 float: left;
 border-radius: 100%;
 }
 
 .activity .time {
 float: right;
 color: #b7b7b7;
 font-style: italic;
 }
 .activity .content {
 margin-left: 60px;
 }
 </style>
 
 <div class="activity">
 <img class="icon" src="" width="40" height="40">
 <div class="time"></div>
 <div class="content"><content></content></div>
 </div>
 </template>
 
 
 <script>
 
 var activityPrototype = Object.create(HTMLElement.prototype);
 
 activityPrototype.createdCallback = function() {
 var template = document.querySelector('template');
 var clone = document.importNode(template.content, true);
 
 var host = $(this);
 $(".icon", clone).attr("src", host.attr("iconSrc"));
 $(".time", clone).text(host.attr("time"));
 
 var shadowRoot = this.createShadowRoot();
 shadowRoot.appendChild(clone);
 };
 
 // Register our new element
 document.registerElement('activity-card', {
 prototype: activityPrototype
 });
 </script>
 
 <div class="activity-stream">
 <h2>Activities</h2>
 <activity-card iconSrc="../img/michael.jpeg" time="Seconds ago">
 <a href="profiles/michael">Michael</a> had fun writing web components.
 </activity-card>
 <activity-card iconSrc="../img/hendrick.jpeg" time="Minutes ago">
 <a href="profiles/hendrick">Hendrick</a> blogged on <a href="http://guigarage.com">GuiGarage</a>.
 </activity-card>
 <activity-card iconSrc="../img/michael.jpeg" time="1 hour ago">
 <a href="profiles/michael">Michael</a> needed an extra large cup of coffee.
 </activity-card>
 <activity-card iconSrc="../img/hendrick.jpeg" time="Yesterday">
 <a href="profiles/hendrick">Hendrick</a> watched a movie.
 </activity-card>
 </div>
 </body>
 </html>
  • 86. <!DOCTYPE html>
 <html>
 <head lang="en">
 <meta charset="UTF-8">
 <title>Activity Stream - Standard Web Component</title>
 <link href="stylesheet.css" rel="stylesheet">
 <script src="bower_components/jquery/dist/jquery.min.js"></script>
 </head>
 <body>
 <template>
 <style>
 * {
 font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
 }
 .activity {
 width: 500px;
 height: 40px;
 padding: 10px;
 background-color: #f0f8ff;
 font-size: small;
 margin: 10px 0;
 }
 .activity .icon {
 float: left;
 border-radius: 100%;
 }
 
 .activity .time {
 float: right;
 color: #b7b7b7;
 font-style: italic;
 }
 .activity .content {
 margin-left: 60px;
 }
 </style>
 
 <div class="activity">
 <img class="icon" src="" width="40" height="40">
 <div class="time"></div>
 <div class="content"><content></content></div>
 </div>
 </template>
 
 
 <script>
 
 var activityPrototype = Object.create(HTMLElement.prototype);
 
 activityPrototype.createdCallback = function() {
 var template = document.querySelector('template');
 var clone = document.importNode(template.content, true);
 
 var host = $(this);
 $(".icon", clone).attr("src", host.attr("iconSrc"));
 $(".time", clone).text(host.attr("time"));
 
 var shadowRoot = this.createShadowRoot();
 shadowRoot.appendChild(clone);
 };
 
 // Register our new element
 document.registerElement('activity-card', {
 prototype: activityPrototype
 });
 </script>
 
 <div class="activity-stream">
 <h2>Activities</h2>
 <activity-card iconSrc="../img/michael.jpeg" time="Seconds ago">
 <a href="profiles/michael">Michael</a> had fun writing web components.
 </activity-card>
 <activity-card iconSrc="../img/hendrick.jpeg" time="Minutes ago">
 <a href="profiles/hendrick">Hendrick</a> blogged on <a href="http://guigarage.com">GuiGarage</a>.
 </activity-card>
 <activity-card iconSrc="../img/michael.jpeg" time="1 hour ago">
 <a href="profiles/michael">Michael</a> needed an extra large cup of coffee.
 </activity-card>
 <activity-card iconSrc="../img/hendrick.jpeg" time="Yesterday">
 <a href="profiles/hendrick">Hendrick</a> watched a movie.
 </activity-card>
 </div>
 </body>
 </html> Component Code Application Code Application Code
  • 88. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Html Import <!DOCTYPE html>
 <html>
 <head lang="en">
 <meta charset="UTF-8">
 <title>Activity Stream - Standard Web Component</title>
 <link href="stylesheet.css" rel="stylesheet">
 <script src="bower_components/jquery/dist/jquery.min.js"></script>
 </head>
 <body>
 <div class="activity-stream">
 <h2>Activities</h2>
 <activity-card iconSrc="../img/michael.jpeg" time="Seconds ago">
 <a href="profiles/michael">Michael</a> had fun writing web components.
 </activity-card>
 <activity-card iconSrc="../img/hendrick.jpeg" time="Minutes ago">
 <a href="profiles/hendrick">Hendrick</a> blogged on <a href="http://guigarage.com">GuiGarage</a>.
 </activity-card>
 <activity-card iconSrc="../img/michael.jpeg" time="1 hour ago">
 <a href="profiles/michael">Michael</a> needed an extra large cup of coffee.
 </activity-card>
 <activity-card iconSrc="../img/hendrick.jpeg" time="Yesterday">
 <a href="profiles/hendrick">Hendrick</a> watched a movie.
 </activity-card>
 </div>
 </body>
 </html> <template>
 <style>
 * {
 font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
 }
 .activity {
 width: 500px;
 height: 40px;
 padding: 10px;
 background-color: #f0f8ff;
 font-size: small;
 margin: 10px 0;
 }
 .activity .icon {
 float: left;
 border-radius: 100%;
 }
 
 .activity .time {
 float: right;
 color: #b7b7b7;
 font-style: italic;
 }
 .activity .content {
 margin-left: 60px;
 }
 </style>
 
 <div class="activity">
 <img class="icon" src="" width="40" height="40">
 <div class="time"></div>
 <div class="content"><content></content></div>
 </div>
 </template>
 
 
 <script>
 
 var activityPrototype = Object.create(HTMLElement.prototype);
 
 activityPrototype.createdCallback = function() {
 var template = document.querySelector('template');
 var clone = document.importNode(template.content, true);
 
 var host = $(this);
 $(".icon", clone).attr("src", host.attr("iconSrc"));
 $(".time", clone).text(host.attr("time"));
 
 var shadowRoot = this.createShadowRoot();
 shadowRoot.appendChild(clone);
 };
 
 // Register our new element
 document.registerElement('activity-card', {
 prototype: activityPrototype
 });
 </script>
  • 89. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Html Import <!DOCTYPE html>
 <html>
 <head lang="en">
 <meta charset="UTF-8">
 <title>Activity Stream - Standard Web Component</title>
 <link href="stylesheet.css" rel="stylesheet">
 <script src="bower_components/jquery/dist/jquery.min.js"></script>
 </head>
 <body>
 <div class="activity-stream">
 <h2>Activities</h2>
 <activity-card iconSrc="../img/michael.jpeg" time="Seconds ago">
 <a href="profiles/michael">Michael</a> had fun writing web components.
 </activity-card>
 <activity-card iconSrc="../img/hendrick.jpeg" time="Minutes ago">
 <a href="profiles/hendrick">Hendrick</a> blogged on <a href="http://guigarage.com">GuiGarage</a>.
 </activity-card>
 <activity-card iconSrc="../img/michael.jpeg" time="1 hour ago">
 <a href="profiles/michael">Michael</a> needed an extra large cup of coffee.
 </activity-card>
 <activity-card iconSrc="../img/hendrick.jpeg" time="Yesterday">
 <a href="profiles/hendrick">Hendrick</a> watched a movie.
 </activity-card>
 </div>
 </body>
 </html> <template>
 <style>
 * {
 font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
 }
 .activity {
 width: 500px;
 height: 40px;
 padding: 10px;
 background-color: #f0f8ff;
 font-size: small;
 margin: 10px 0;
 }
 .activity .icon {
 float: left;
 border-radius: 100%;
 }
 
 .activity .time {
 float: right;
 color: #b7b7b7;
 font-style: italic;
 }
 .activity .content {
 margin-left: 60px;
 }
 </style>
 
 <div class="activity">
 <img class="icon" src="" width="40" height="40">
 <div class="time"></div>
 <div class="content"><content></content></div>
 </div>
 </template>
 
 
 <script>
 
 var activityPrototype = Object.create(HTMLElement.prototype);
 
 activityPrototype.createdCallback = function() {
 var template = document.querySelector('template');
 var clone = document.importNode(template.content, true);
 
 var host = $(this);
 $(".icon", clone).attr("src", host.attr("iconSrc"));
 $(".time", clone).text(host.attr("time"));
 
 var shadowRoot = this.createShadowRoot();
 shadowRoot.appendChild(clone);
 };
 
 // Register our new element
 document.registerElement('activity-card', {
 prototype: activityPrototype
 });
 </script> activity-card.html
  • 90. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Html Import <!DOCTYPE html>
 <html>
 <head lang="en">
 <meta charset="UTF-8">
 <title>Activity Stream - Standard Web Component</title>
 <link href="stylesheet.css" rel="stylesheet">
 <script src="bower_components/jquery/dist/jquery.min.js"></script>
 </head>
 <body>
 <div class="activity-stream">
 <h2>Activities</h2>
 <activity-card iconSrc="../img/michael.jpeg" time="Seconds ago">
 <a href="profiles/michael">Michael</a> had fun writing web components.
 </activity-card>
 <activity-card iconSrc="../img/hendrick.jpeg" time="Minutes ago">
 <a href="profiles/hendrick">Hendrick</a> blogged on <a href="http://guigarage.com">GuiGarage</a>.
 </activity-card>
 <activity-card iconSrc="../img/michael.jpeg" time="1 hour ago">
 <a href="profiles/michael">Michael</a> needed an extra large cup of coffee.
 </activity-card>
 <activity-card iconSrc="../img/hendrick.jpeg" time="Yesterday">
 <a href="profiles/hendrick">Hendrick</a> watched a movie.
 </activity-card>
 </div>
 </body>
 </html> <template>
 <style>
 * {
 font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
 }
 .activity {
 width: 500px;
 height: 40px;
 padding: 10px;
 background-color: #f0f8ff;
 font-size: small;
 margin: 10px 0;
 }
 .activity .icon {
 float: left;
 border-radius: 100%;
 }
 
 .activity .time {
 float: right;
 color: #b7b7b7;
 font-style: italic;
 }
 .activity .content {
 margin-left: 60px;
 }
 </style>
 
 <div class="activity">
 <img class="icon" src="" width="40" height="40">
 <div class="time"></div>
 <div class="content"><content></content></div>
 </div>
 </template>
 
 
 <script>
 
 var activityPrototype = Object.create(HTMLElement.prototype);
 
 activityPrototype.createdCallback = function() {
 var template = document.querySelector('template');
 var clone = document.importNode(template.content, true);
 
 var host = $(this);
 $(".icon", clone).attr("src", host.attr("iconSrc"));
 $(".time", clone).text(host.attr("time"));
 
 var shadowRoot = this.createShadowRoot();
 shadowRoot.appendChild(clone);
 };
 
 // Register our new element
 document.registerElement('activity-card', {
 prototype: activityPrototype
 });
 </script> activity-card.html <link rel="import" href="activity-card.html">
  • 91. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Html Import 36+ and Android Browser 37 26+
  • 93. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 webcomponent.js • Today not all browsers support the new standards • The community provides a pollyfills to enable web components in browser that have no native support $ bower install --save webcomponentsjs <script src="bower_components/webcomponentsjs/webcomponents.js"></script> install it with bower use it in your code
  • 94. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 webcomponent.js • The polyfills are the junction of X-Tag and Polymer basic libraries • Mozilla created X-Tag as a polyfill to provide web components • Google created Polymer as a polyfill to provide web components
  • 95. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 webcomponent.js • X-Tag and Polymer depends on webcomponents-js • Both libraries provide additional features that are not part of the specification webcomponents.org
  • 97. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Polymer • Adds sugar on top of web components • Easy to use • Extendable • Polymer is created & supported by Google
  • 98. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Polymer • Separated in several parts: • Polymer API • Iron Elements • Paper Elements • … www.polymer-project.org
  • 99. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Polymer
  • 100. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Iron Elements • Iron Elements are low level components • Most Paper UI components base on Iron • Icons, layouts …
  • 101. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Icons
  • 102. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Icons
  • 103. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Google Web Components • Google is building a lot of components (maps, youtube…) <google-chart></google-chart> <google-hangout-button></google-hangout-button>
  • 105. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Polymer Paper • Complete component library based on Material Design
  • 106.
  • 107.
  • 108.
  • 109.
  • 110. Bower
  • 111. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Bower • A package manager for the web • Search for dependencies and install them as packages • Created by Twitter • Open Source www.bower.io
  • 112. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Bower requires npm, node.js and git $ npm install -g bower $ bower init $ bower install --save webcomponentsjs in your project folder download & add module add dependency to bower file
  • 114. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 How to use Components • All components are build as web components • A single component or a set can be added by using bower $ bower install --save Polymer/paper-slider <link rel="import" href="bower_components/paper-slider/paper-slider.html"> import it in HTML
  • 115. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Paper Button • The default Button • shows ripple animation on click <paper-button>flat button</paper-button> <paper-button raised>raised button</paper-button> <paper-button noink>No ripple effect</paper-button>
  • 116. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Paper CheckBox • A styled CheckBox • State can be defined as attribute <paper-checkbox></paper-checkbox> <paper-checkbox checked></paper-checkbox>
  • 117. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Paper Dialog • A dialog • Supports title, modality, actions, … <paper-dialog heading="Title"> <p>Some content</p> </paper-dialog>
  • 118. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Overview
  • 119. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Overview
  • 120. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Layout • HeaderPanel • Toolbar • DrawerPanel • Scaffold
  • 121. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Toolbar • An application toolbar • Toolbar content will be aligned <core-toolbar> <paper-icon-button icon="menu"></paper-icon-button> <div>My Application</div> <span flex></span> <paper-icon-button icon="event"></paper-icon-button> </core-toolbar>
  • 122. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 HeaderPanel • Wrapper around toolbar and content • Toolbar always on top • Content scrollable <core-header-panel flex> <core-toolbar>Title</core-toolbar> <div>content</div> </core-header-panel>
  • 123. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 DrawerPanel • Adds a responsive menu • Defines attributes to open and close the menu • Normally wraps 2 core- header-panel
  • 124. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 DrawerPanel <core-drawer-panel> <core-header-panel drawer> <core-toolbar></core-toolbar> <core-menu> <core-item label="One"></core-item> </core-menu> </core-header-panel> <core-header-panel main> <core-toolbar> <paper-icon-button core-drawer-toggle icon="menu"></paper-icon-button> </core-toolbar> <div>content</div> </core-header-panel> </core-drawer-panel> drawer panel main panel show drawer
  • 125. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Scaffold • Basic skeleton • Best practice to create an application • Contains all the shown features <core-scaffold> <core-header-panel navigation flex> <!-- nav drawer --> </core-header-panel> <span tool>Title</span> <div>content</div> </core-scaffold> defines the drawer defines the main toolbar
  • 127. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Paper Demo • Create a new folder • Install needed modules with Bower $ mkdir app $ cd app $ bower init $ bower install --save PolymerElements/paper-elements
  • 128. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Paper Demo • Create index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> </head> <body>Hello World</body> </html>
  • 129. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Paper Demo • add webcomponents.js • 
<head> . . . <script src=„bower_components/webcomponentsjs/webcomponents.js"> </script> </head>
  • 130. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Paper Demo • add Roboto Font • 
<head> <link rel="import" href=„bower_components/font-roboto/ roboto.html"> <style> html,body { font-family: 'RobotoDraft', sans-serif; } </style> </head>
  • 131. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Paper Demo
  • 132. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Paper Demo • add a header panel with a toolbar <body class="fullbleed layout vertical">
 <paper-header-panel class="flex">
 <paper-toolbar>Title</paper-toolbar>
 </paper-header-panel>
 </body>
 <link rel=„import" href="bower_components/paper-styles/paper-styles.html"> <link rel=„import" href="bower_components/paper-header-panel/paper-header-panel.html"> <link rel="import" href="bower_components/paper-toolbar/paper-toolbar.html">
  • 133. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Paper Demo
  • 134. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Paper Demo • Add some content to the toolbar <link rel=„import" href="bower_components/iron-icons/iron-icons.html"> <link rel="import" href="bower_components/paper-icon-button/paper-icon-button.html"> <paper-toolbar>
 <paper-icon-button icon="menu"></paper-icon-button>
 <span class="flex">Title</span>
 <paper-icon-button icon="add"></paper-icon-button>
 <paper-icon-button icon="remove"></paper-icon-button>
 </paper-toolbar>
  • 135. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Paper Demo
  • 136. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Paper Demo • Add paper elements as content <link rel="import" href=„bower_components/paper-input/paper-input.html"> <link rel="import" href="bower_components/paper-button/paper-button.html"> <div class="layout vertical"> <paper-input label="Name"></paper-input> <paper-input label="Description"></paper-input> <paper-button raised>save</paper-button> </div>
  • 137. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Paper Demo
  • 138. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Paper Demo • Add some padding .content { padding: 20px; } <div class="content layout vertical"> <paper-input label="Name"></paper-input> <paper-input label="Description"></paper-input> <paper-button raised>save</paper-button> </div>
  • 139. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Paper Demo
  • 142. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Custom Components • Polymer can be used to create custom web components • Defines a nice and modern API to create components • Adds several features on top of the spec
  • 143. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 A First Example <link rel=„import" href="bower_components/polymer/polymer.html">
  • 144. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 A First Example <link rel=„import" href="bower_components/polymer/polymer.html"> <dom-module id="dom-element"> </dom-module>
  • 145. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 A First Example <link rel=„import" href="bower_components/polymer/polymer.html"> <dom-module id="dom-element"> <template> <p>I'm a DOM element. This is my local DOM!</p> </template> </dom-module>
  • 146. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 A First Example <link rel=„import" href="bower_components/polymer/polymer.html"> <dom-module id="dom-element"> <template> <p>I'm a DOM element. This is my local DOM!</p> </template> <script> Polymer({is: "dom-element"}); </script> </dom-module>
  • 147. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 • Component name must contain a "-" • Polymer script call must be included • Template is not needed • Once it is created it can be used as custom tag Custom Components
  • 148. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Lifecycle • Polymer defines it’s own lifecycle that is based on the Web Component Spec lifecycle • Callbacks can simply be defined in Polymer
  • 149. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Difference to Spec • created instead of createdCallback • attached instead of attachedCallback • detached instead of detachedCallback • attributeChanged instead of attributeChangedCallback
  • 150. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Additional Callback • Polymer adds an extra callback ready which is invoked when Polymer has finished creating and initializing the element’s local DOM. • The created callback is always called before ready. • The ready callback is always called before attached.
  • 151. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Example<script> Polymer({ is: „dom-element“, ready: function () { console.log('Ready!'); }, detached: function() { console.log(this.localName + '#' + this.id + ' was detached'); }, attributeChanged: function(name, type) { console.log('Attribute ' + name + ' was changed'); } }); </script>
  • 152. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Property • Properties can be specified for a Polymer component • A property can be of the following types: • Boolean, Date, Number, String, Array or Object
  • 153. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Property • Properties can be defined in JavaScript Polymer({ is: 'my-component', properties: { user: String, isHappy: Boolean } });
  • 154. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Property • Properties can be set in JavaScript
 
 
 
 Properties can be set as HTML attribute ready: function () { this.set(‘user‘,’unknown‘); } <my-component user=‘unknown‘></my-component>
  • 155. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Property • Default value can be specified properties: { user: { type: String, value: ‘unknown‘ }, isHappy: Boolean }
  • 156. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Data Binding • binds a property to an attribute of an element
 
 • Use [[prop]] for one-way-binding • Property defines if {{prop}} is one-way or bidirectional binding <child-element name="{{myName}}"></child-element>
  • 157. Ok, let’s create an application
  • 158. Mockup
  • 159. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0
  • 160. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0
  • 162. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Application Basic Layout • Header with fixed size
 • Resizeable main area
 • Footer with fixed size
  • 163. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Polymer Layout • The Polymer layout is based on flexbox • Use Polymer layout classes to simplify the usage of flexbox
  • 164. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Flexbox • New CSS 3 layout • Flexbox consists of flex containers and flex items. box box box container
  • 165. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Flexbox • Contents can be laid out in any flow direction (leftwards, rightwards, downwards, or even upwards!) • Contents can be laid out linearly along a single (main) axis or wrapped into multiple lines along a secondary (cross) axis • Contents can “flex” their sizes to respond to the available space • …
  • 166. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Flexbox box box box container flex-direction: row; box box box container flex-direction:column;
  • 167. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Flexbox box box box container flex: 0; flex: 0;flex: 1;
  • 168. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Application Basic Layout fix height fix height dynamic height flexbox
  • 169. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Using Flex Box in Polymer • Polymer defines several layout classes • layout: basic class that must be set • horizontal: layout content in a row • vertical: layout content in a column • flex: content will fill space
  • 170. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Polymer Layout Alpha Beta Gamma <div class="horizontal layout"> <div>Alpha</div> <div class="flex">Beta (flex)</div> <div>Gamma</div> </div>
  • 172. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Application Structure • A Polymer application is based on web components • The components define a hierarchy • chat-view component contains several chat-bubble components
  • 173. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Application Structure
  • 174. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Application Structure Yeah! message-view
  • 175. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 chat-bubble Application Structure Yeah! message-view
  • 176. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 chat-view chat-bubble Application Structure Yeah! message-view
  • 177. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 app-view chat-view chat-bubble Application Structure Yeah! message-view
  • 178. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Like building futuristic Matrjoschkas with Lego
  • 179. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Application Structure • The demo will use bower to handle all dependencies • Real applications should use a build script • like Gulp or Grunt
  • 180. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 index.html • add web components polyfill script • Import basic dependencies like Roboto- Font and Polymer layouts • body contains only one web component: the application
  • 181. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 imports 
 <script src="bower_components/webcomponentsjs/webcomponents.js"></script>
 
 <link rel="import" href="bower_components/paper-styles/paper-styles.html">
 <link rel="import" href="bower_components/font-roboto/roboto.html">

  • 182. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 imports 
 <script src="bower_components/webcomponentsjs/webcomponents.js"></script>
 
 <link rel="import" href="bower_components/paper-styles/paper-styles.html">
 <link rel="import" href="bower_components/font-roboto/roboto.html">
 web components polyfill font and layouts
  • 183. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 component-xy.html • Contains the definition of one web component • All components that are needed internally should be imported
  • 184. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Workspace bower.json index.html chat-bubble.html chat-view.html chat-header.html chat-footer.html chat-app.html
  • 186. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Chat Bubble Sender This is the chat message. The size of the bubble should fit to this message. Next to normal text emojis can be part of a message: 😊 5 min ago
  • 187. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Chat Bubble Sender This is the chat message. The size of the bubble should fit to this message. Next to normal text emojis can be part of a message: 😊 5 min ago depends on parent width dependsontextlength
  • 188. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Chat Bubble Sender This is the chat message. The size of the bubble should fit to this message. Next to normal text emojis can be part of a message: 😊 5 min ago dependsontext length fix fix
  • 189. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Chat Bubble Sender This is the chat message. The size of the bubble should fit to this message. Next to normal text emojis can be part of a message: 😊 5 min ago fix
  • 190. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Chat Bubble
  • 191. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Chat Bubble <div id="bubble"><div> #bubble {
 background-color: #F2F2F2;
 border-radius: 5px;
 }
  • 192. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Chat Bubble Sender This is the chat message. The size of the bubble should fit to this message. Next to normal text emojis can be part of a message: 😊 5 min ago
  • 193. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Chat Bubble <div id="bubble"><div> #bubble {
 background-color: #F2F2F2;
 border-radius: 5px; padding: 2px 12px 2px 12px; }
  • 194. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Chat Bubble
  • 195. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 CSS ::after Selector p::after {
 content: " - Remember this";
 } • The ::after selector inserts something after the content of each selected element(s). • Use the content property to specify the content to insert.
  • 196. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Chat Bubble #bubble::after {
 background-color: #F2F2F2;
 display: block;
 position: absolute;
 content: "00a0";
 height: 16px;
 width: 20px;
 bottom: 11px;
 transform: rotate(29deg) skew(-35deg);
 }
  • 197. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Chat Bubble Web Component <dom-module id=„chat-bubble"> <style> #bubble { . . . } </style> 
 <template> <div id=„bubble"> . . . </div> </template> 
 </dom-module> 
 <script> Polymer({
 is: "chat-bubble" }); </script>
  • 198. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Chat Bubble Attributes • Sender & message should be dynamic • Can be defined as attributes of the component • Use Polymer properties properties: {
 text: String,
 sender: String
 }
  • 199. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Problem
  • 200. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 configure Bubble with CSS #bubble {
 . . .
 } • We can specify 2 separate CSS classes: me and you .me { . . . } .you { . . . }
  • 201. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 • We can dynamically change the CCS class in JS code • Access bubble div in Polymer
 • Mutate class list change Css class bubbleDiv.classList.remove('me');
 bubbleDiv.classList.add('you'); var bubbleDiv = this.$.bubble; id of the div
  • 202. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 • Polymer provides observers for properties
 
 • Observer will be called whenever property values changes Property Observer me: { type: Boolean,
 observer: ‚_senderChanged' } _senderChanged: function (newValue, oldValue) {
 this.updateStyleClass(newValue);
 }
  • 203. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 • The initial boolean property value reflects if a HTML attribute is set use boolean property <chat-bubble me></chat-bubble> <chat-bubble></chat-bubble> „me“ property == true „me“ property == false
  • 205. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Chat View • Should contain a list of chat bubbles • Scrollable • based on data array (JSON)
  • 206. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Polymer Iron • List of low level components • Define behavior • Don’t define theme / skin
  • 207. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0
  • 208. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 iron-list • Defines a list that can be scrolled • Can contain thousands of elements. Only visible area is rendered • Define a template for each cell
  • 209. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 iron-list <iron-list items="[[data]]" as="item">
 <template>
 <chat-bubble text=„[[item.message]]" …></chat-bubble>
 </template>
 </iron-list>
  • 210. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 provide dummy data <iron-ajax url="data.json" last-response="{{messages}}" auto></iron-ajax>
 • Polymer provides Iron Element to load JSON data
  • 212. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Centered Text • The name should be centered • Layout should not be effected by other nodes .centered {
 top: 18px;
 left: 0;
 position:absolute;
 width: 100%;
 } .title {
 font-size: 22px;
 text-align:center;
 } parent of text text
  • 213. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Rounded Image • Avatar image should be rounded .avatar {
 width: 64px;
 height: 64px;
 border-radius: 32px;
 border-style: solid;
 border-width: 1px;
 border-color: lightgrey;
 }
  • 214. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Dynamic content • Add some Polymer properties
 
 
 • Use them inline
 Properties: {
 title: String,
 state: String
 } <div class="centered vertical layout">
 <div class="title">{{title}}</div>
 <div class="subtitle">{{state}}</div>
 </div>
  • 216. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Custom Textbox • <input> can be styled with CSS • Polymer provides a behavior to add data binding to a normal input <input is="iron-input" value="{{message::input}}">
  • 217. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Custom Button • Call a internal web component function when the button is clicked <button on-click="sendMyMessage">send</button> Polymer({
 is: "input-view",
 sendMyMessage: function (e) {…}
 });
  • 218. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Polymer events • Web Components can fire events
 • Observer can be added
 • Hint: trigger a resize for iron-list when content changes:
 this.fire('message-send', {message: this.message}); <input-view on-message-send="send"></input-view> this.$.itemsList.fire('resize');
  • 220. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 About Emojis • All emojis are defined by a a unicode character
  • 221. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Emojis in HTML • Most OS provide a font to render emojis • As long as the browser supports unicode and your files are encoded in unicode you can use them
  • 222. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Parse Emojis • Cool lib with word - emoji mapping can be found here: 
 github.com/muan/emojilib • A Polymer Emoji selector can be found here:
 github.com/notwaldorf/emoji-selector
  • 223. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Emojis in the chat var converted = '';
 var words = input.split(' ');
 for (var i = 0; i < words.length; i++) {
 var emoji = getMeAnEmoji(words[i]);
 if(emoji != '') {
 converted = converted + ' ' + emoji;
 } else {
 converted = converted + ' ' + words[i];
 }
 }
  • 225.
  • 226. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Dolphin Platform • Enterprise Framework with Presentation Model pattern • Server centric logic • Spring and JavaEE integration
  • 227. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Dolphin Platform • JavaFX, AngularJS & Google Polymer client APIs
 
 
 
 
 … More will come
  • 228. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Dolphin Platform
  • 229. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Model • Defined in Java • Hierarchical models are no problem • Full observable • Collection support
  • 230. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Model @DolphinBean public class MyModel { private Property<String> name; public Property<String> nameProperty() {return name;} } Dolphin Platform propere can be used on client and server This is NOT a JFXProperty
  • 231. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Controller • Controller is defined on the server • Will be managed by the container (Spring, JavaEE, …) • Full CDI support
  • 232. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Controller @DolphinController public class MyController { @DolphinModel private MyModel model; @PostConstruct public void init() { model.nameProperty().onChange(e -> System.out.println(„CHANGE“)); } } Inject the model Use containerfeatures
  • 233. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 View • The smallest part ;) • Use the complete UI Toolkit power • Simply bind your view to the model • Trigger controller actions
  • 234. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 View <dom-module id="my-view"> <template> <paper-input label="Task name" value="{{model.name}}"></paper-input> </template> </dom-module> <script> Polymer({ is: "my-view", behaviors: [clientContext.createBehavior('MyController')] }); </script> Dolphin Platform providesPolymer behavior Server controller Dolphin Platformmodel
  • 236. PolymerWeb Components & by Sending a message Client Server
  • 237. PolymerWeb Components & by Sending a message Client Server call DolphinAction
  • 238. PolymerWeb Components & by Sending a message Client Server Event Bus call DolphinAction
  • 239. PolymerWeb Components & by Sending a message Client Server Event Bus call DolphinAction publish
  • 240. PolymerWeb Components & by Sending a message Client Server Event Bus call DolphinAction publish
  • 241. PolymerWeb Components & by Sending a message Client Server Event Bus call DolphinAction publish notify
  • 242. PolymerWeb Components & by Sending a message Client Presentation Model Server Event Bus call DolphinAction publish notify
  • 243. PolymerWeb Components & by Sending a message Client Presentation Model Server Event Bus call DolphinAction publish notifyupdate
  • 244. PolymerWeb Components & by Sending a message Client Presentation Model Server Event Bus call DolphinAction publish notifyupdate
  • 245. PolymerWeb Components & by Sending a message Client Presentation Model Server Event Bus call DolphinAction publish notifyupdate synced automatically
  • 246. PolymerWeb Components & by client code diff
  • 248. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Additional Topics • Behaviors • Animations • Custom CSS properties • DOM manipulation
  • 249. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Additional Topics • Polymer contains more features • Explorer the Polymer Catalog
 • Read the documentation https://elements.polymer-project.org https://www.polymer-project.org/1.0/docs/
  • 251. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Real World • Todo
  • 253. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Polymer Starter Kit • Fully functional mini-application • Defines application structure • Contains many useful configurations
 (e.g. for gitignore, jshint, travis) • Sophisticated build script • Sidenote: all files contain copyright headers
  • 254. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Polymer Starter Kit • Minification ( js, css, images) • Inlining of HTML Imports • Cache Config for Offline Usage • Local Server (with browser-sync) • Testing
  • 256. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Web Component Tester npm install -g web-component-tester wct Installation Usage
  • 257. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Web Component Tester • Integrates Mocha, Chai, and Sinon • Runs with Selenium • Integration with Sauce Labs provided • By default runs all tests in test/ • Tasks for grunt and gulp available
 (though gulp integration is sub-optimal)
  • 258. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Web Component Tester <head>
 <meta charset="utf-8">
 <script src="../bower_components/webcomponentsjs/webcomponents.min.js"> </script>
 <script src="/web-component-tester/browser.js"></script>
 <link rel="import" href="../chat-bubble.html">
 </head>
  • 259. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Web Component Tester <head>
 <meta charset="utf-8">
 <script src="../bower_components/webcomponentsjs/webcomponents.min.js"> </script>
 <script src="/web-component-tester/browser.js"></script>
 <link rel="import" href="../chat-bubble.html">
 </head> web component polyfill
  • 260. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Web Component Tester <head>
 <meta charset="utf-8">
 <script src="../bower_components/webcomponentsjs/webcomponents.min.js"> </script>
 <script src="/web-component-tester/browser.js"></script>
 <link rel="import" href="../chat-bubble.html">
 </head>
  • 261. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Web Component Tester <head>
 <meta charset="utf-8">
 <script src="../bower_components/webcomponentsjs/webcomponents.min.js"> </script>
 <script src="/web-component-tester/browser.js"></script>
 <link rel="import" href="../chat-bubble.html">
 </head> provided by wct
  • 262. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Web Component Tester <head>
 <meta charset="utf-8">
 <script src="../bower_components/webcomponentsjs/webcomponents.min.js"> </script>
 <script src="/web-component-tester/browser.js"></script>
 <link rel="import" href="../chat-bubble.html">
 </head>
  • 263. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Web Component Tester <head>
 <meta charset="utf-8">
 <script src="../bower_components/webcomponentsjs/webcomponents.min.js"> </script>
 <script src="/web-component-tester/browser.js"></script>
 <link rel="import" href="../chat-bubble.html">
 </head> component under test
  • 264. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Web Component Tester <body> <test-fixture id="chatBubbleFixture">
 <template>
 <chat-bubble></chat-bubble>
 </template>
 </test-fixture> ...
  • 265. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Web Component Tester <body> <test-fixture id="chatBubbleFixture">
 <template>
 <chat-bubble></chat-bubble>
 </template>
 </test-fixture> ... provided by wct
  • 266. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Web Component Tester <body> <test-fixture id="chatBubbleFixture">
 <template>
 <chat-bubble></chat-bubble>
 </template>
 </test-fixture> ...
  • 267. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Web Component Tester <body> <test-fixture id="chatBubbleFixture">
 <template>
 <chat-bubble></chat-bubble>
 </template>
 </test-fixture> ... web component under test
  • 268. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Web Component Tester<script>
 describe('<chat-bubble>', function() {
 it('should show the sender', function(done) {
 var chatBubble = fixture('chatBubbleFixture');
 chatBubble.set('sender', 'Test Sender');
 setTimeout(function () {
 expect(chatBubble.$$('.sender')) .to.have.property('textContent')
 .that.contains('Test Sender');
 done();
 });
 });
 });
 </script>
  • 269. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Web Component Tester<script>
 describe('<chat-bubble>', function() {
 it('should show the sender', function(done) {
 var chatBubble = fixture('chatBubbleFixture');
 chatBubble.set('sender', 'Test Sender');
 setTimeout(function () {
 expect(chatBubble.$$('.sender')) .to.have.property('textContent')
 .that.contains('Test Sender');
 done();
 });
 });
 });
 </script> create component
  • 270. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Web Component Tester <script>
 describe('<chat-bubble>', function() {
 it('should show the sender', function(done) {
 var chatBubble = fixture('chatBubbleFixture');
 chatBubble.set('sender', 'Test Sender');
 setTimeout(function () {
 expect(chatBubble.$$('.sender')) .to.have.property('textContent')
 .that.contains('Test Sender');
 done();
 });
 });
 });
 </script>
  • 271. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Web Component Tester <script>
 describe('<chat-bubble>', function() {
 it('should show the sender', function(done) {
 var chatBubble = fixture('chatBubbleFixture');
 chatBubble.set('sender', 'Test Sender');
 setTimeout(function () {
 expect(chatBubble.$$('.sender')) .to.have.property('textContent')
 .that.contains('Test Sender');
 done();
 });
 });
 });
 </script> set property
  • 272. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Web Component Tester<script>
 describe('<chat-bubble>', function() {
 it('should show the sender', function(done) {
 var chatBubble = fixture('chatBubbleFixture');
 chatBubble.set('sender', 'Test Sender');
 setTimeout(function () {
 expect(chatBubble.$$('.sender')) .to.have.property('textContent')
 .that.contains('Test Sender');
 done();
 });
 });
 });
 </script>
  • 273. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Web Component Tester<script>
 describe('<chat-bubble>', function() {
 it('should show the sender', function(done) {
 var chatBubble = fixture('chatBubbleFixture');
 chatBubble.set('sender', 'Test Sender');
 setTimeout(function () {
 expect(chatBubble.$$('.sender')) .to.have.property('textContent')
 .that.contains('Test Sender');
 done();
 });
 });
 });
 </script> needs to be asynchronous
  • 274. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Web Component Tester<script>
 describe('<chat-bubble>', function() {
 it('should show the sender', function(done) {
 var chatBubble = fixture('chatBubbleFixture');
 chatBubble.set('sender', 'Test Sender');
 setTimeout(function () {
 expect(chatBubble.$$('.sender')) .to.have.property('textContent')
 .that.contains('Test Sender');
 done();
 });
 });
 });
 </script>
  • 275. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Web Component Tester<script>
 describe('<chat-bubble>', function() {
 it('should show the sender', function(done) {
 var chatBubble = fixture('chatBubbleFixture');
 chatBubble.set('sender', 'Test Sender');
 setTimeout(function () {
 expect(chatBubble.$$('.sender')) .to.have.property('textContent')
 .that.contains('Test Sender');
 done();
 });
 });
 });
 </script> DOM-query
  • 276. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Web Component Tester module.exports = {
 plugins: {
 sauce: {
 browsers: [
 {
 platform: 'Windows 8.1',
 browserName: 'internet explorer',
 version: '11.0'
 }
 ]
 }
 }
 };
  • 277. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Web Component Tester module.exports = {
 plugins: {
 sauce: {
 browsers: [
 {
 platform: 'Windows 8.1',
 browserName: 'internet explorer',
 version: '11.0'
 }
 ]
 }
 }
 }; environment configuration
  • 279. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Situation • All components are part of our project • We can’t reuse them in other projects • The components are not isolated • Looks like a bad mixup
  • 280. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0
  • 281. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 Wish list • We want reusable components • A component should be independent and isolated • Components can depend on each other / include other custom components • Use a component as a bower dependency
  • 282.
  • 283. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 seed-element • Blueprint for custom component • Defines demo, test, and main section • Web component tester and polyserve integrated
  • 284. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 polyserve • Polymer offers a special web server to create reusable components • serves project files under /components/ {bower-name}/ • other component are served from ./ bower_components/
  • 285. PolymerWeb Components & by Questions: https://goo.gl/iZI3l0 polyserve • Your component can refer to external components like your component is in the bower_components folder • Simple to create a github repo for one specific reusable component • Polymer Paper is doing the same