Polymer 1.0

70
Polymer 1.0 @cbalit

Transcript of Polymer 1.0

Polymer 1.0 @cbalit

About me...

Cyril Balit CTO Front

@cbalit

Components

@polymer #itshackademic

<paper-tabs>

<paper-tab>KNOWLEDGE</paper-tab>

<paper-tab>HISTORY</paper-tab>

<paper-tab>FOOD</paper-tab>

</paper-tabs>

Less Code. Less confusion.

Web Components

HTMLIMPORTS

SHADOWDOM

TEMPLATES CUSTOMELEMENTS

Web Components

To define your own HTML tag

Custom Element

<body>

...

<script>

var XFoo = document.registerElement('x-foo', {

prototype: Object.create(HTMLElement.prototype)

});

</script>

<x-foo></x-foo>

</body>

To encapsulate subtree and style in an element

Shadow DOM

<button>Hello, world!</button>

<script>

var host = document.querySelector('button');

var root = host.createShadowRoot();

root.textContent = 'こんにちは、影の世界 !';

</script>

To include an html page in another one

HTML Imports

<link rel="import" href="warnings.html">

<script>

var link = document.querySelector('link[rel="import"]');

var content = link.import;

// Grab DOM from warning.html's document.

var el = content.querySelector('.warning');

document.body.appendChild(el.cloneNode(true));

</script>

To have clonable document template

Template

<template id="mytemplate">

<img src="" alt="great image">

<div class="comment"></div>

</template>

var t = document.querySelector('#mytemplate');

// Populate the src at runtime.

t.content.querySelector('img').src = 'logo.png';

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

document.body.appendChild(clone);

Polyfills...

Photo: http://bit.ly/1CeBPyN

Polymer elements

<paper-checkbox></paper-checkbox>

<paper-input floatinglabel

label="Type only numbers... (floating)"

validate="^[0-9]*$"

error="Input is not a number!">

</paper-input>

A simple container with a headersection and a content section

<paper-header-panel>

<paper-header-panel flex>

<paper-toolbar>

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

</paper-icon-button>

<div>MY APP</div>

</paper-toolbar>

<div>…</div>

</paper-header-panel>

MY APP

<paper-drawer-panel>

<paper-drawer-panel>

<div drawer> Drawer panel... </div>

<div main> Main panel... </div>

</paper-drawer-panel>

And in 2016...

Polymer CLI

npm install -g polymer-cli

polymer init

polymer test

polymer lint

polymer serve

polymer build

New elements… for your application

Container<app-header-layout>

<app-header-layout flex>

<app-header fixed condenses

effects="waterfall">

<app-toolbar>

<div title>App name</div>

</app-toolbar>

</app-header>

<div>…</div>

</app-header-layout>

Headers<app-header>

● Behavior○ fixed○ reveals○ condenses

● Scroll Effects○ waterfall○ parallax

Router

<app-location route="{{route}}"></app-location>

<app-route

route="{{route}}"

pattern="/:view"

data="{{routeData}}"

tail="{{subroute}}"></app-route>

And in 2016...

Coming soon ...

● ES6○ optional

● Custom element V1○ lifecycle changes

● Shadow Dom V1○ slot

● Closer to the standard○ no more polymer.fire….

● January 2017

Make my component

<dom-module id="paper-card"> <style> :host { border-radius: 2px; } .card-header ::content img { width: 70px; border-radius: 50%; } paper-material { border-radius: 2px; } </style> <template> <paper-material elevation="{{elevation}}" animated on-tap=”tapAction”> <div class="card-header layout horizontal center”> <content select="img"></content> <h3>{{heading}}</h3> </div> <content></content> </paper-material> </template></dom-module><script> Polymer({ is:'paper-card', properties: { heading: {type: String, reflectToAttribute: true, value: “”}, elevation: {type: Number, reflectToAttribute: true, value: 1} }, attached: function() { /* your initialisations here */ }, tapAction: function (e) { /* your event handling here */ } });</script>sc

ript /

pro

toty

pethe name must have a “-”

published attributes

tags

/ sh

adow

DO

M a

nd s

tyle

Anatomy of a component

Polyfills

<html>

<head>

<script src="webcomponents/webcomponents-lite.min.js"></script>

</head>

<body>

</body>

</html>

Import your element

<html>

<head>

<script src="webcomponents/webcomponents-lite.min.js"></script>

<link rel="import" href="paper-card.html">

</head>

<body>

</body>

</html>

Use it<html>

<head>

<script src="webcomponents/webcomponents-lite.min.js"></script>

<link rel="import" href="paper-card.html">

</head>

<body>

<paper-card heading="hello my friend">

<img src="avatar.svg">

</paper-card>

</body>

</html>

API of an element

● Attributes

● Properties

● Methods

● Events

● type

● default value

● observers

● notification

Polymer({

is: 'x-custom',

properties: {

userName: String,

count: {

type: Number,

value: 5

observer: '_countChanged',

notify: true

}

_countChanged: function(newVal, oldVal) {}

}

});

<x-custom on-count-changed="do()"></x-custom>

Properties

● dispatch with fire

● can send datas

Polymer({

is: 'x-custom',

handleClick: function() {

this.fire('kick', {kicked: true});

}

});

<x-custom></x-custom>

<script>

document.querySelector('x-custom').addEventListener

('kick', function (e) {

console.log(e.detail.kicked); // true

})

</script>

Events

Get and use Polymer({

is: 'x-custom',

doSomething: function() {

...

}

});

<x-custom></x-custom>

<script>

var elmt=document.querySelector('x-custom');

elmt.doSomething();

</script>

Method

SUGAR

● [[]] : one-way bindings OR host to child

● {{}} : automatic binding (one way or two way according to the configuration)

Data Binding : 2 way

<dom-module id="host-element">

<template>

<child-element name="{{myName}}"></child-element>

</template>

</dom-module>

● iterate on a list

● filter/sort feature<dom-module id="employee-list">

<template>

<template is="dom-repeat" items="{{employees}}">

<div># <span>{{index}}</span></div>

<div>First name: <span>{{item.first}}</span></div>

</template>

</template>

</dom-module>

Helpers : dom-repeat

● Conditional Template <dom-module id="user-page">

<template>

<template>

All users will see this:

<div>{{user.name}}</div>

<template is="dom-if" if="{{user.isAdmin}}">

Only admins will see this.

<div>{{user.secretAdminStuff}}</div>

</template>

</template>

</dom-module>

Helpers : dom-if

<div class="horizontal layout">

<div>One</div>

<div>Two</div>

<div>Three</div>

</div>

● compute properties

● behavior

● flex layout

● ...

And also

Styling

with shadow dom, new selectors

● :host

● ::content

● Cross scope Styling

○ ::shadow et /deep/

source :http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom-201/

CSS et Shadow Dom

compatible with the futur W3C CSS Custom Properties

<dom-module id="my-button">

<template>

<style>

.title {

color: var(--my-toolbar-title-color,red);

}

:host {

@apply(--my-button-theme);

}

</style>

</template>

</dom-module>

<style>

.submit {

--my-toolbar-title-color: green;

}

.special {

--my-button-theme:{

padding:20px;

backgound-color:red;

}

</style>

<my-button class="submit"></my-button>

<my-button class="special"></my-button>

Custom CSS properties / mixins

Use cases

An implementation of the google-recaptcha component

<re-captcha>

<re-captcha

sitekey="yoursitekey"></re-captcha>

source: https://github.com/cbalit/re-captcha

A authentification component

<frf-login>

<frf-login loginurl=“/login"

logouturl=“/logout">

<span>C’est qui ?</span>

</frf-login>

Architecture

frf-login

frf-user

frf-login-form

frf-confirm

html5-paper-input

frf-login-service

core-ajax

API

Applications...

Integration

API of an element

● Attributes

● Properties

● Methods

● Events

The promise

Write once ...

...run everywhere

ui: {

$frfLogin: 'frf-login'},

events: {

'login-success frf-login': 'onLogin',},

onLogin: function (e) {

this.ui.$frfLogin.hide(); var userDatas=this.ui.$frfLogin.get(0).getCurrentUser();}

Just an HTML element<div class="views"> <frf-login login-url="{{loginUrl}}" logout-url="{{logoutUrl}}"> <span id="title">franfinance</ span> </frf-login></div>

render() { reactPolymer.registerAttribute('login-url'); reactPolymer.registerEvent('login-success','login-success'); return ( <div> <link rel="import" href="frf-login/frf-login.html"/> <div className="views"> <frf-login ref="frfLogin" login-url={loginUrl} logout-url={logoutUrl} login-success={this.onLogin}> <span id="title">C'est qui ?</span> </frf-login> </div> </div> );}onLogin(event) { var userDatas = this.refs.frfLogin.getDOMNode().getCurrentUser();}

I need some help

https://github.com/jscissr/react-polymer

<frf-login id="loginCpnt" login-url='{{login.config.loginUrl}}' login-success="login.onlogin($pEvent)" login-ready="login.onready()" bind-polymer-event="login-success,login-ready"> </frf-login>

Listening to an event

https://github.com/cbalit/bind-polymer-event

this.frfElemt = document.getElementById ('loginCpnt');if (this.frfElemt.isUserAuthenticated ()) { var userInfo = this.frfElemt.getCurrentUser ().toJSON(); this.proceedLogin(userInfo);}

<link rel="import" href="/bower_components/google-map/google-map.html"><link rel="import" href="/bower_components/google-map/google-map-marker.html">

<section class="map" *ngIf="displayMap"> <google-map map-type="roadmap" latitude="48.8534100" longitude="2.3488000" fit-to-markers api-key="xxx"> <google-map-marker *ngFor="let person of people" latitude="{{person.geo.lat}}" longitude="{{person.geo.lng}}"> </google-map-marker> </google-map></section>

Just let me know you’re a WC...

@NgModule({

imports: [],

declarations: [],

schemas: [ CUSTOM_ELEMENTS_SCHEMA ]})

Tooling

Polymer CLI

npm install -g polymer-cli

polymer init

polymer test

polymer lint

polymer serve

polymer build

bower install --save Polymer/polymer#^1.0.0

bower install --save PolymerElements/iron-elements

bower install --save PolymerElements/paper-elements

bower install --save PolymerElements/gold-elements

Bower

npm install -g generator-polymer

yo polymer (polymer:app)

yo polymer:el

yo polymer:seed

yo polymer:gh

Yeoman

npm install -g web-component-tester

wtc

OR

bower install Polymer/web-component-tester --save

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

Web Components Tester

https://github.com/cbalit/re-captcha

Example

● PolyUp

● PolyServe

● PolyLint

● Vulcanize

● Crisper

● PolyBuild

● ...

And also

thank’s!

Cyril Balit@cbalit