Sara HARKOUSSE
RuhrJS
Bochum, 14,15 October 2017
http://vignette2.wikia.nocookie.net/weirdcommunity/images/a/a2/Rainbow-flow-abstract-backgrounds-for-powerpoint.jpg/revision/latest?cb=20130603085532
@Sara_harkousse
Tech Lead, front-end Web developer at Dassault Systèmes
3D design & PLM software
Electronics and Computer Science Engineer by training
@RuhrJS #webcomponents
Duchess France
@duchessfr
duchess-france.org
Elles bougent (Girls on The Move)
@ellesbougent
ellesbougent.com
@RuhrJS #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"
@RuhrJS #webcomponents @Sara_harkousse
@RuhrJS #webcomponents @Sara_harkousse
"The broken promise of Web Components"
@RuhrJS #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
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://embed.plnkr.co/?show=preview&show=app%2Fapp.component.ts
@RuhrJS #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.12.0/components/defining-a-component/
// 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
@RuhrJS #webcomponents @Sara_harkousse
@RuhrJS #webcomponents @Sara_harkousse
https://www.webcomponents.org/
@RuhrJS #webcomponents @Sara_harkousse
https://www.webcomponents.org/
@RuhrJS #webcomponents @Sara_harkousse
@RuhrJS #webcomponents @Sara_harkousse
@RuhrJS #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
@RuhrJS #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
@RuhrJS #webcomponents @Sara_harkousse
@RuhrJS #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>
@RuhrJS #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);
@RuhrJS #webcomponents @Sara_harkousse
https://www.webcomponents.org/
@RuhrJS #webcomponents @Sara_harkousse
https://www.webcomponents.org/
// export feature
export const Component = // …
// import feature
import {Component} from '../components/cutom-component.js';
@RuhrJS #webcomponents @Sara_harkousse
@RuhrJS #webcomponents @Sara_harkousse
@RuhrJS #webcomponents @Sara_harkousse
@RuhrJS #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);
}
@RuhrJS #webcomponents @Sara_harkousse
/* Use it */
:host {
color: red;
}
/* Don't use it */
custom-component {
color: red;
}
@RuhrJS #webcomponents @Sara_harkousse
if (shadowflag){
this.root = this.attachShadow({mode: 'open'});
} else {
this.root = this;
}
custom-component, :host {
color: red;
}
@RuhrJS #webcomponents @Sara_harkousse
class CustomButton extends HTMLElement {...}
window.customElements.define('custom-button', CustomButton);
<custom-button></custom-button>
@RuhrJS #webcomponents @Sara_harkousse
class CustomButton extends HTMLButtonElement {...}
window.customElements.define('custom-button', CustomButton, {extends: 'button'});
<button is="custom-button" disabled>My button!</button>
@RuhrJS #webcomponents @Sara_harkousse
@RuhrJS #webcomponents @Sara_harkousse
class Custom-component extends HTMLElement {
constructor() {
super(); // always call super() first in the ctor.
...
}
connectedCallback() {
...
}
disconnectedCallback() {
...
}
attributeChangedCallback(attrName, oldVal, newVal) {
...
}
}
@RuhrJS #webcomponents @Sara_harkousse
<div class="progress">
<div class="progress-bar" style="width: 60%;">
60%
</div>
</div>
window.customElements.define('progress-bar', ProgressBar);
// Use
<progress-bar></progress-bar>
https://jsfiddle.net/sara_harkousse/kwwe75yy/
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);
}
static get observedAttributes() {
return ['complete'];
}
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 + '%';
}
}
connectedCallback() {
var template = `<div class="progress-bar">
<div class="progress-bar-inner">${this.complete}%</div>
</div>`;
this.shadow.innerHTML = template;
}
}
@RuhrJS #webcomponents @Sara_harkousse
@RuhrJS #webcomponents @Sara_harkousse
<!doctype html>
<html lang="en">
<head>
<link rel="import" href="/imports/productRow.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 }
}));
document.querySelector('progress-bar').addEventListener(
'customevent', function () {
// do something
}
});
</script>
</body>
</html>
@RuhrJS #webcomponents @Sara_harkousse
@RuhrJS #webcomponents @Sara_harkousse
@RuhrJS #webcomponents
@Sara_harkousse
https://github.com/SaraHarkousse