Sara HARKOUSSE
DevFest Nantes
19, 20 Octobre 2017
http://vignette2.wikia.nocookie.net/weirdcommunity/images/a/a2/Rainbow-flow-abstract-backgrounds-for-powerpoint.jpg/revision/latest?cb=20130603085532
http://vignette2.wikia.nocookie.net/weirdcommunity/images/a/a2/Rainbow-flow-abstract-backgrounds-for-powerpoint.jpg/revision/latest?cb=20130603085532
#devfestnantes #webcomponents @Sara_harkousse
@Sara_harkousse
Tech Lead, front-end Web developer at Dassault Systèmes
3D design & PLM software
Electronics and Computer Science Engineer by training
#devfestnantes #webcomponents
Duchess France
@duchessfr
duchess-france.org
Elles bougent (Girls on The Move)
@ellesbougent
ellesbougent.com
#devfestnantes #webcomponents @Sara_harkousse
http://vignette2.wikia.nocookie.net/weirdcommunity/images/a/a2/Rainbow-flow-abstract-backgrounds-for-powerpoint.jpg/revision/latest?cb=20130603085532
"The web components revolution"
"A Tectonic shift for web development"
"Web components are a game changer"
#devfestnantes #webcomponents @Sara_harkousse
#devfestnantes #webcomponents @Sara_harkousse
"The broken promise of Web Components"
#devfestnantes #webcomponents @Sara_harkousse
#devfestnantes #webcomponents @Sara_harkousse
Filterable Product Table
Search Bar
Product Table
Product Row
Product Category Row
https://facebook.github.io/react/docs/thinking-in-react.html
#devfestnantes #webcomponents @Sara_harkousse
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `<h1>Hello {{name}}</h1>`
})
export class AppComponent { name = 'Angular'; }
<my-app><h1>Hello Angular</h1></my-app>
https://angular.io/tutorial/toh-pt1#show-the-hero
#devfestnantes #webcomponents @Sara_harkousse
<article class="blog-post">
<h1>{{title}}</h1>
<p>{{yield}}</p>
<p>Edit title: {{input type="text" value=title}}</p>
</article>
{{#each model as |post|}}
{{#blog-post title=post.title}}
{{post.body}}
{{/blog-post}}
{{/each}}
https://guides.emberjs.com/v2.16.0/components/defining-a-component/
#devfestnantes #webcomponents @Sara_harkousse
// Define the class for a new element called custom-element
class CustomElement extends Polymer.Element {
static get is() { return "custom-element"; }
constructor() {
super();
this.textContent = "I'm a custom-element.";
}
}
// Register the new element with the browser
customElements.define(CustomElement.is, CustomElement);
<custom-element></custom-element>
http://plnkr.co/edit/PaCt2M?p=preview
#devfestnantes #webcomponents @Sara_harkousse
#devfestnantes #webcomponents @Sara_harkousse
https://www.webcomponents.org/
#devfestnantes #webcomponents @Sara_harkousse
https://www.webcomponents.org/
#devfestnantes #webcomponents @Sara_harkousse
#devfestnantes #webcomponents @Sara_harkousse
#devfestnantes #webcomponents @Sara_harkousse
<template id="template">
<div id="container">
<img class="webcomponents" src="logo.svg">
</div>
</template>
https://github.com/SaraHarkousse/Web_Components/tree/master/VanillaJS/Template
#devfestnantes #webcomponents @Sara_harkousse
var template = document.querySelector('#template');
var clone = template.content.cloneNode(true);
var host = document.querySelector('#host');
host.appendChild(clone);
https://github.com/SaraHarkousse/Web_Components/tree/master/VanillaJS/Template
#devfestnantes #webcomponents @Sara_harkousse
#devfestnantes #webcomponents @Sara_harkousse
#devfestnantes #webcomponents @Sara_harkousse
#devfestnantes #webcomponents @Sara_harkousse
#devfestnantes #webcomponents @Sara_harkousse
callback() {
// Use it
this.root = this.attachShadow({mode: 'open'});
var template = document.querySelector('#template');
var clone = document.importNode(template.content, true);
this.root.appendChild(clone);
}
callback() {
// Don't Use it
this.root = this;
var template = document.querySelector('#template');
var clone = document.importNode(template.content, true);
this.root.appendChild(clone);
}
#devfestnantes #webcomponents @Sara_harkousse
/* Use it */
:host {
color: red;
}
/* Don't use it */
custom-component {
color: red;
}
#devfestnantes #webcomponents @Sara_harkousse
if (shadowflag){
this.root = this.attachShadow({mode: 'open'});
} else {
this.root = this;
}
custom-component, :host {
color: red;
}
#devfestnantes #webcomponents @Sara_harkousse
class CustomButton extends HTMLElement {...}
window.customElements.define('custom-button', CustomButton);
<custom-button></custom-button>
#devfestnantes #webcomponents @Sara_harkousse
class CustomButton extends HTMLButtonElement {...}
window.customElements.define('custom-button', CustomButton, {extends: 'button'});
<button is="custom-button" disabled>My button!</button>
#devfestnantes #webcomponents @Sara_harkousse
#devfestnantes #webcomponents @Sara_harkousse
class Custom-component extends HTMLElement {
constructor() {
super(); // always call super() first in the ctor.
...
}
connectedCallback() {
...
}
disconnectedCallback() {
...
}
attributeChangedCallback(attrName, oldVal, newVal) {
...
}
}
#devfestnantes #webcomponents @Sara_harkousse
<link rel="import" href="component.html">
<link rel="stylesheet" href="style.css">
<div id="container">
<img class="rotate" src="logo.svg">
</div>
<script src="script.js"></script>
[Deprecation] Styling master document from stylesheets defined in HTML Imports is deprecated, and is planned to be removed in M65, around March 2018. Please refer to https://goo.gl/EGXzpw for possible migration paths.
#devfestnantes #webcomponents @Sara_harkousse
var link = document.querySelector('link[rel="import"]');
var content = link.import;
// Grab DOM from component.html's document.
var el = content.querySelector('#container');
var clone = el.cloneNode(true);
var host = document.querySelector('#host');
host.appendChild(clone);
#devfestnantes #webcomponents @Sara_harkousse
#devfestnantes #webcomponents @Sara_harkousse
#devfestnantes #webcomponents @Sara_harkousse
https://www.webcomponents.org/
#devfestnantes #webcomponents @Sara_harkousse
// export feature
export const Component = // …
// import feature
import {Component} from '../components/cutom-component.js';
#devfestnantes #webcomponents @Sara_harkousse
<div class="progress">
<div class="progress-bar" style="width: 60%;">
60%
</div>
</div>
#devfestnantes #webcomponents @Sara_harkousse
class ProgressBar extends HTMLElement {
constructor() {
super(); // always call super() first in the ctor.
this.shadow = this.attachShadow({mode: 'open'});
this._complete = 0;
}
get complete() {
return this._complete;
}
set complete(val) {
this.setAttribute('complete', val);
}
}
https://jsfiddle.net/sara_harkousse/kwwe75yy/
#devfestnantes #webcomponents @Sara_harkousse
class ProgressBar extends HTMLElement {
static get observedAttributes() {
return ['complete'];
}
attributeChangedCallback(name, oldval, newval) {
// code
}
}
https://jsfiddle.net/sara_harkousse/kwwe75yy/
#devfestnantes #webcomponents @Sara_harkousse
class ProgressBar extends HTMLElement {
attributeChangedCallback(name, oldval, newval) {
var innerBar = this.shadow.querySelector('.progress-bar-inner');
switch(name) {
case 'complete':
this._complete = parseInt(newval, 10) || 0;
innerBar.style.width = this.complete + '%';
innerBar.innerHTML = this.complete + '%';
}
}
}
https://jsfiddle.net/sara_harkousse/kwwe75yy/
#devfestnantes #webcomponents @Sara_harkousse
class ProgressBar extends HTMLElement {
connectedCallback() {
var template = `<style>
.progress-bar {
width: 50%;
...
}
.progress-bar-inner {
height: 100%;
....
}
</style>
<div class="progress-bar">
<div class="progress-bar-inner">${this.complete}%</div>
</div>`;
this.shadow.innerHTML = template;
}
}
https://jsfiddle.net/sara_harkousse/kwwe75yy/
#devfestnantes #webcomponents @Sara_harkousse
window.customElements.define('progress-bar', ProgressBar);
// Use
<progress-bar></progress-bar>
#devfestnantes #webcomponents @Sara_harkousse
<!doctype html>
<html lang="en">
<head>
<link rel="import" href="/components/CustomNavbar.html">
..
</head>
<body>
<custom-navbar style="compact"></custom-navbar>
<custom-toolbar style="full"></custom-toolbar>
<custom-pagecontent>
<custom-input attr="val"></custom-input>
<progress-bar></progress-bar>
</custom-pagecontent>
<script>
document.querySelector('custom-input').dispatchEvent(new CustomEvent('customevent', {
detail: { prop: true }
}));
customElements.whenDefined('progress-bar').then(() => {
document.querySelector('progress-bar').addEventListener(
'customevent', function () {
// do something
}
});
});
</script>
</body>
</html>
#devfestnantes #webcomponents @Sara_harkousse
#devfestnantes #webcomponents @Sara_harkousse
#devfestnantes #webcomponents
@Sara_harkousse
https://github.com/SaraHarkousse