</> htmx 2.0 & Web Components: A Perfect Match for Frontend Development

A presentation at FinistDevs in September 2024 in Brest, France by Horacio Gonzalez

Slide 1

Slide 1

</> htmx 2.0 & Web Components Un combo pour le développement web Horacio Gonzalez 2024-09-12

Slide 2

Slide 2

Horacio Gonzalez @LostInBrittany Espagnol Perdu en Bretagne

Slide 3

Slide 3

Créez des interfaces utilisateur modernes avec la simplicité et la puissance de l’hypertexte

Slide 4

Slide 4

Les limites arbitraires du HTML ● Pourquoi seules les balises <a> et <form> peuvent-elles effectuer des requêtes HTTP(S) ? ● Pourquoi seuls les événements de clic et d’envoi peuvent-ils les déclencher ? ● Pourquoi seules les méthodes GET et POST sont-elles disponibles ? ● Pourquoi les balises <a> et <form> forcent le remplacement de l’intégralité de l’écran ? ● Pourquoi autant des limites arbitraires à HTML ?

Slide 5

Slide 5

Objectif: de l’interactivité dans l’hypertexte htmx étend les fonctionnalités de HTML ● effectuer des requêtes AJAX ● effectuer des transitions CSS ● gérer des WebSockets ● gérer les événements envoyés par le serveur avec seulement des attributs HTML déclaratifs.

Slide 6

Slide 6

Mais à quoi ça sert tout ça ? Car c’est bien beau et sémantique, mais j’ai du mal à voir l’intérêt…

Slide 7

Slide 7

Et si on faisait un petit saut arrière dans le temps ? À une époque révolue, où les dinosaurs codaient avec struts

Slide 8

Slide 8

Souvenez-vous du modèle MVC Avec la navigation page par page

Slide 9

Slide 9

L’époque dorée d’une génération de frameworks Generant des vues HTML

Slide 10

Slide 10

Vers 2005 on voit arriver AJAX C’est la naissance du Web 2.0

Slide 11

Slide 11

Et les pages webs deviennent des apps dynamiques À coup de JavaScript, avec JQuery

Slide 12

Slide 12

On bascule vers des Single Page Apps

Slide 13

Slide 13

Des apps de plus en plus complexes Avec l’apparition des frameworks JavaScript

Slide 14

Slide 14

Et les backends deviennent des API REST Servant du JSON

Slide 15

Slide 15

On a gagné des fonctionnalités Mais on a perdu de la simplicité et le côté sémantique

Slide 16

Slide 16

Pour beaucoup d’app c’est overkill On ne veut qu’un site web avec un peu de dynamisme !

Slide 17

Slide 17

</> htmx peut être la bonne solution C’est du HTML étendu ● Simplicité ● Sémantique ● Dynamisme

Slide 18

Slide 18

On veut du code ! Des exemples ! Des exemples ! example-01.html <script src=”https://unpkg.com/htmx.org@2.0.2”></script> <!— have a button that POST on a click via AJAX and replace the content of #status div with the response —> <button hx-post=”/clicked” hx-target=”#status”> Click Me </button> <div id=”status”>Not yet clicked</div>

Slide 19

Slide 19

Trop de blabla, on veut un exemple ! example-01.html <script src=”https://unpkg.com/htmx.org@2.0.2”></script> <!— have a button that POST on a click via AJAX and replace the content of #status div with the response —> <button hx-post=”/clicked” hx-target=”#status”> Click Me </button> <div id=”status”>Not yet clicked</div>

Slide 20

Slide 20

GET, POST, PUT, DELETE… example-02.html <script src=”https://unpkg.com/htmx.org@2.0.2”></script> <div> <button hx-get=”/test-methods” hx-target=”#status”>Send GET</button> <button hx-post=”/test-methods” hx-target=”#status”>Send POST</button> <button hx-put=”/test-methods” hx-target=”#status”>Send PUT</button> <button hx-delete=”/test-methods” hx-target=”#status”>Send DELETE</button> </div> <div id=”status”>No request sent</div>

Slide 21

Slide 21

Remplacer l’élément par la réponse example-03.html <script src=”https://unpkg.com/htmx.org@2.0.2”></script> <div id=”test-replace”> <button hx-get=”/test-replace/innerHTML”> If you click, this message will be replaced </button> <button hx-get=”/test-replace/outerHTML” hx-swap=”outerHTML”> If you click, this button will become a div </button> <button hx-get=”/test-replace/delete” hx-swap=”delete”> If you click, this button will dissapear when the response is received </button> <button hx-get=”/test-replace/none” hx-swap=”none”> If you click, nothing changes, the response is ignored </button> </div>

Slide 22

Slide 22

Choisir quand émettre la requête example-04.html <script src=”https://unpkg.com/htmx.org@2.0.2”></script> <!— By default, AJAX requests are triggered by the “natural” event of an element: —> <div id=”test-triggers”> <button hx-get=”/trigger/natural” hx-target=”#status”> In a button the natural event is a click </button> <button hx-trigger=”mouseover” hx-get=”/trigger/mouseover” hx-target=”#status”> This button triggers on mouseover </button> <button hx-trigger=”mouseenter” hx-get=”/trigger/mouseenter” hx-target=”#status”> This button triggers on mouseenter </button> <button hx-trigger=”mouseleave” hx-get=”/trigger/mouseleave” hx-target=”#status”> This button triggers on mouseleave </button> </div> <div id=”status”>No AJAX request sent yet</div>

Slide 23

Slide 23

Choisir quand émettre la requête example-05.html <script src=”https://unpkg.com/htmx.org@2.0.2”></script> <!— By default, AJAX requests are triggered by the “natural” event of an element: —> <div id=”test-triggers”> <button hx-trigger=”every 5s” hx-get=”/trigger/5seconds” hx-target=”#status”> Sends request every 5 seconds, no event needed </button> <button hx-trigger=”click[ctrlKey]” hx-get=”/trigger/ctrlclick” hx-target=”#status”> Sends request on click while pressing Ctrl </button> <button hx-trigger=”click[ctrlKey] once” hx-get=”/trigger/ctrlclickonce” hx-target=”#status”> Sends request on the first click while pressing Ctrl </button> </div> <div id=”status”>No AJAX request sent yet</div>

Slide 24

Slide 24

Un spinner pour faire patienter example-06.html <script src=”https://unpkg.com/htmx.org@2.0.2”></script> <!— By default, AJAX requests are triggered by the “natural” event of an element: —> <div id=”test-triggers”> <button hx-trigger=”every 5s” hx-get=”/trigger/5seconds” hx-target=”#status”> Sends request every 5 seconds, no event needed </button> <button hx-trigger=”click[ctrlKey]” hx-get=”/trigger/ctrlclick” hx-target=”#status”> Sends request on click while pressing Ctrl </button> <button hx-trigger=”click[ctrlKey] once” hx-get=”/trigger/ctrlclickonce” hx-target=”#status”> Sends request on the first click while pressing Ctrl </button> </div> <div id=”status”>No AJAX request sent yet</div>

Slide 25

Slide 25

Des extensions presque à l’infini

Slide 26

Slide 26

On veut du code ! Faisons un exemple

Slide 27

Slide 27

Tout le code est disponible https://github.com/LostInBrittany/introduction-to-htmx

Slide 28

Slide 28

Des démos de htmx Du Hello World à la To-do List

Slide 29

Slide 29

What the heck are web component? The 3 minutes context

Slide 30

Slide 30

Web Components Web standard W3C

Slide 31

Slide 31

Web Components Available in all modern browsers: Firefox, Safari, Chrome

Slide 32

Slide 32

Web Components Create your own HTML tags Encapsulating look and behavior

Slide 33

Slide 33

Web Components Fully interoperable With other web components, with any framework

Slide 34

Slide 34

Web Components CUSTOM ELEMENTS SHADOW DOM TEMPLATES

Slide 35

Slide 35

Custom Element To define your own HTML tag <body> … <script> window.customElements.define(‘my-element’, class extends HTMLElement {…}); </script> <my-element></my-element> </body>

Slide 36

Slide 36

Shadow DOM To encapsulate subtree and style in an element <button>Hello, world!</button> <script> var host = document.querySelector(‘button’); const shadowRoot = host.attachShadow({mode:’open’}); shadowRoot.textContent = ‘こんにちは、影の世界!’; </script>

Slide 37

Slide 37

Template To have clonable document 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);

Slide 38

Slide 38

But in fact, it’s just an element… ● ● ● ● Attributes Properties Methods Events

Slide 39

Slide 39

Simple. Fast. Web Components

Slide 40

Slide 40

Modern lightweight web components For the new web paradigm

Slide 41

Slide 41

LitElement import { LitElement, html } from ‘lit-element’; // Create your custom component class CustomGreeting extends LitElement { // Declare properties static get properties() { return { name: { type: String } }; } // Initialize properties constructor() { super(); this.name = ‘World’; } // Define a template render() { return html<p>Hello, ${this.name}!</p>; } } // Register the element with the browser customElements.define(‘custom-greeting’, CustomGreeting); Lightweight web-components using lit-html

Slide 42

Slide 42

Based on lit-html An efficient, expressive, extensible HTML templating library for JavaScript

Slide 43

Slide 43

Do you know tagged templates? function uppercaseExpression(strings, …expressionValues) { var finalString = ” for ( let i = 0; i < strings.length; i++ ) { if (i > 0) { finalString += expressionValues[i - 1].toUpperCase() } finalString += strings[i] } return finalString } const expressions = [ ‘Sophia Antipolis’, ‘RivieraDev’, ‘Thank you’]; console.log(uppercaseJe suis à ${expression[0]} pour ${expression[1]. $expression[2]! Little known functionality of template literals

Slide 44

Slide 44

lit-html Templates let myTemplate = (data) => html<h1>${data.title}</h1> <p>${data.body}</p>; Lazily rendered Generates a TemplateResult

Slide 45

Slide 45

It’s a bit like JSX, isn’t it? The good sides of JSX… but in the standard!

Slide 46

Slide 46

LitElement import { LitElement, html } from ‘lit-element’; // Create your custom component class CustomGreeting extends LitElement { // Declare properties static get properties() { return { name: { type: String } }; } // Initialize properties constructor() { super(); this.name = ‘World’; } // Define a template render() { return html<p>Hello, ${this.name}!</p>; } } // Register the element with the browser customElements.define(‘custom-greeting’, CustomGreeting); Lightweight web-components using lit-html

Slide 47

Slide 47

Une petit démo de Lit Faisons un compteur : my-lit-counter

Slide 48

Slide 48

Lit & </> htmx Amour au premier <tag>

Slide 49

Slide 49

htmx pour structure, lit pour encapsuler l’intelligence Pour htmx les élément lits sont comme n’importe quel tag

Slide 50

Slide 50

Une petit démo de htmx + Lit Faisons un compteur : my-lit-counter

Slide 51

Slide 51

That’s all, folks! Thank you all!