Adrian Faciu
Principal software engineer. Focused on front-end. Learning something new each day. Building things at WeVideo.
@adrianfaciu
@adrianfaciu
define new HTML tags
composition
encapsulation
@adrianfaciu
@adrianfaciu
@adrianfaciu
webcomponents.org
@adrianfaciu
@adrianfaciu
browser APIs
LitElement
@adrianfaciu
@adrianfaciu
@adrianfaciu
@adrianfaciu
// Create spans
var wrapper = document.createElement('span');
wrapper.setAttribute('class','wrapper');
var icon = document.createElement('span');
icon.setAttribute('class','icon');
icon.setAttribute('tabindex', 0);
var info = document.createElement('span');
info.setAttribute('class','info');
shadow.appendChild(wrapper);
wrapper.appendChild(info);
@adrianfaciu
@adrianfaciu
<form #itemForm="ngForm"
(ngSubmit)="onSubmit(itemForm)">
<label for="name"
>Name <input class="form-control"
name="name"
ngModel
required />
</label>
<button type="submit">Submit</button>
</form>
<div [hidden]="!itemForm.form.valid">
<p>{{ submitMessage }}</p>
</div>
@adrianfaciu
const myTemplate = (
<>
<form onSubmit={handleSubmit}>
<label for="name"
>Name <input class="form-control"
name="name"
value={inputvalue}
onChange={handleChange}
required />
</label>
<button type="submit">Submit</button>
</form>
<div hidden={isValid}>
<p>{submitMessage}</p>
</div>
</>
);
@adrianfaciu
@adrianfaciu
@adrianfaciu
`string text`
`string text line 1
string text line 2`
`string text ${expression} string text`
@adrianfaciu
tag`string text ${expression} string text`
@adrianfaciu
import { html } from 'lit-html';
const myTemplate = html`<div>Hello World</div>`;
@adrianfaciu
import { html } from 'lit-html';
let myTemplate = (data) => html`
<h1>${data.title}</h1>
<p>${data.body}</p>`;
@adrianfaciu
const myTemplate = (data) =>
html`<div class=${data.cssClass}>${data.text}</div>`;
@adrianfaciu
const myTemplate = (data) =>
html`<div ?disabled=${data.active}>Item is active</div>`;
@adrianfaciu
const myTemplate = (data) =>
html`<my-list .listItems=${data.items}></my-list>`;
@adrianfaciu
const myTemplate = () =>
html`<button @click=${clickHandlerFn}>Click Me!
</button>`;
const clickHandlerFn = (e) =>
console.log('clicked!');
const clickHandlerObj = {
handleEvent(e) {
console.log('clicked!');
},
};
@adrianfaciu
@adrianfaciu
const myHeader = html`<h1>Header</h1>`;
const myPage = html`
${myHeader}
<div>Here's my main page.</div>
`;
@adrianfaciu
@adrianfaciu
const items = {
a: 1,
b: 23,
c: 456,
};
const list = () =>
html`items = ${Object.entries(items)}`;
@adrianfaciu
html`
<ul>
${items.map((i) => html`<li>${i}</li>`)}
</ul>
`;
@adrianfaciu
html`
${user.isloggedIn
? html`Welcome ${user.name}`
: html`Please log in`
}
`;
@adrianfaciu
@adrianfaciu
import { html, render } from 'lit-html';
// A lit-html template uses the `html` template tag:
let sayHello = (name) => html`<h1>Hello ${name}</h1>`;
// It's rendered with the `render()` function:
render(sayHello('World'), document.body);
// And re-renders only update the data that changed
// without VDOM diffing!
render(sayHello('Everyone'), document.body);
@adrianfaciu
@adrianfaciu
@adrianfaciu
import { html, render } from 'lit-html';
import { until } from 'lit-html/directives/until.js';
const fetchData = () =>
new Promise(resolve =>
setTimeout(() => resolve(50), 1000));
const template = () => html`
Count: <span>${until(fetchData(), html`Loading`)}</span>
`
render(template(), document.body);
@adrianfaciu
import { repeat } from 'lit-html/directives/repeat';
const myTemplate = () => html`
<ul>
${repeat(items, (i) => i.id, (i, index) => html`
<li>${index}: ${i.name}</li>`)}
</ul>
`;
@adrianfaciu
import {unsafeHTML}
from 'lit-html/directives/unsafe-html.js';
const markup = '<div>Some HTML to render.</div>';
const template = html`
Look out, potentially unsafe HTML ahead:
${unsafeHTML(markup)}
`;
@adrianfaciu
@adrianfaciu
import { LitElement, html, property, customElement }
from 'lit-element';
@customElement('simple-greeting')
export class SimpleGreeting extends LitElement {
@property() name = 'World';
render() {
return html`<p>Hello, ${this.name}!</p>`;
}
}
@adrianfaciu
import { LitElement, html, property, customElement }
from 'lit-element';
@customElement('simple-greeting')
export class SimpleGreeting extends LitElement {
@property() name = 'World';
render() {
return html`<p>Hello, ${this.name}!</p>`;
}
}
<simple-greeting name="Everyone"></simple-greeting>
@adrianfaciu
@property
@customElement
@query
@eventOptions
@adrianfaciu
@adrianfaciu
export class MyElement extends LitElement {
@property({ type: String }) prop1 = '';
}
@adrianfaciu
export class MyElement extends LitElement {
// properties getter
static get properties() {
return {
prop1: { type: String }
};
}
constructor() {
// Always call super() first
super();
this.prop1 = 'Hello World';
}
}
@adrianfaciu
<my-element
prop1="hello world"
prop2="5"
prop3
prop4='{"stuff":"hi"}'
prop5='[1,2,3,4]'></my-element>
@adrianfaciu
@adrianfaciu
render() {
return html`
<button @click="${this.handleClick}">`;
}
@adrianfaciu
this.addEventListener('click', this.handleClick);
@adrianfaciu
@adrianfaciu
let click = new Event('click');
this.dispatchEvent(click);
let event = new CustomEvent('my-event', {
detail: {
message: 'Something important happened'
}
});
this.dispatchEvent(event);
@adrianfaciu
@adrianfaciu
@adrianfaciu
@adrianfaciu
@adrianfaciu
import { LitElement, css, html }
from 'lit-element';
class MyElement extends LitElement {
static get styles() {
return css`
div { color: red; }
`;
}
render() {
return html`
<div>I'm styled!</div>
`;
}
}
@adrianfaciu
@adrianfaciu
slides.com/adrianfaciu/litelement
By Adrian Faciu
Principal software engineer. Focused on front-end. Learning something new each day. Building things at WeVideo.