Adrianistán

El blog de Adrián Arroyo


htmx, o como sería HTML si se tomase el hipertexto en serio

- Adrián Arroyo Calle

Hoy os traigo un framework web con el que últimamente estoy jugando bastante. Se llama htmx y a diferencia de otros frameworks como React o Vue, aquí no escribiremos JavaScript. Escribiremos más HTML siguiendo la filosofía original del hipertexto. ¿Intrigado? Sigue leyendo.

¿Qué es el hipertexto?

Se define hipertexto como una estructura no jerárquica, no secuencial donde nodos se enlazan entre sí a través de enlaces. La web es el ejemplo más claro de hipertexto. Podemos saltar de una página a otra haciendo click en enlaces. Pero en realidad las webs modernas no son documentos 100% atómicos. La mayoría tienen varios componentes. Estos componentes en el desarrollo web tradicional no son nodos dentro de la red de hipertexto. ¿Y si sí lo fueran? Es decir, que las diferentes componentes de una web fuesen un nodo dentro del hipertexto. Si esto lo mezclamos con imágenes y el vídeo (que ya siguen este esquema) entramos de lleno dentro del mundo de la hipermedia.

En el mundo de la hipermedia las APIs no devuelven XML o JSON, sino devuelven HTML que a su vez devuelven más acciones dentro de la aplicación. Un poco como HATEOAS pero donde el humano es el que decide. htmx sigue esta filosofía. De este modo vamos a poder escribir grandes aplicaciones web de forma declarativa dentro del propio HTML. Un enfoque totalmente diferente a React o Angular.

Primeros pasos con htmx

La clave de htmx es poder generar peticiones HTTP desde más sitios. El resultado de esas peticiones, serán en muchos casos documentos HTML parciales, que podemos luego mostrar donde queramos.

Para instalar htmx, lo primero es importar la librería:


<script src="https://unpkg.com/htmx.org@1.6.1"></script>

Para definir el verbo de la petición, añadimos los atributos hx-get, hx-post, hx-put, hx-delete u hx-patch con valor la URL a donde se debe dirigir la petición. Si no indicamos nada más, se asignará el trigger más natural dependiendo del elemento. El trigger es aquella acción que hace que se dispare la petición. Podemos sobreescribirlo con el atributo hx-trigger. Un ejemplo:


   <div hx-post="/mouse_entered" hx-trigger="mouseenter">
      [Here Mouse, Mouse!]
   </div>

Este código hará una llamada POST a /mouse_entered cuando el ratón pase por encima. La respuesta se mostrará en el propio div.

Los triggers a su vez pueden llevar modificadores como limitar a solo una vez la acción, dejar un retraso entre peticiones mínimo, solo hacer la petición si ha habido cambios, etc...

Más cosas que hay que saber sobre htmx

Por defecto htmx escribe la respuesta de la petición dentro del propio elemento. Eso se puede modificar con el atributo hx-target que toma selectores CSS. Además, por defecto se hace un swap de tipo "innerHTML", es decir, se escribe en el interior del HTML. Pero puede hacerse de más formas: outerHTML, afterbegin, beforebegin,...

htmx además admite añadir contenido a las peticiones HTTP, mediante los atributos hx-include y hx-params.

Además de todo esto, htmx se integra con CSS y podemos tener animaciones para los elementos nuevos y spinners de carga de forma muy sencilla.

Un detalle a tener en cuenta es que htmx se va heredando a los elementos hijos. Es decir, si tenemos un atributo htmx en alguna etiqueta, lo más probable es que a los elementos dentro de esa etiqueta también les aplique.

Por último, mencionar que htmx se puede extender mediante JavaScript y mediante HyperScript, un lenguaje del mismo creador de htmx, con la idea de ser muy sencillo de usar justo para estos casos.

La documentación es bastante clara y se puede buscar con facilidad.

ActiveSearch en htmx

Un ejemplo más avanzado para ver htmx es una tabla sobre la que podemos realizar búsquedas. Las búsquedas se realizan en el servidor, que devuelve solo las filas que cumplen las condiciones.


<h3> 
  Search Contacts 
  <span class="htmx-indicator">
    <img src="/img/bars.svg"/> Searching... 
   </span> 
</h3>
<input class="form-control" type="text" 
       name="search" placeholder="Begin Typing To Search Users..." 
       hx-post="/search" 
       hx-trigger="keyup changed delay:500ms" 
       hx-target="#search-results" 
       hx-indicator=".htmx-indicator">

<table class="table">
    <thead>
    <tr>
      <th>First Name</th>
      <th>Last Name</th>
      <th>Email</th>
    </tr>
    </thead>
    <tbody id="search-results">
    </tbody>
</table>

En la foto se ve que ocurre al introducir Venus en la caja de búsqueda. Se realiza una petición POST a /search. Esta envía un payload de tipo application/x-www-form-urlencoded con search="Venus". La petición se lanza cuando dejamos de presionar una tecla en el teclado, el valor ha cambiado y se espera medio segundo antes de enviarla. La respuesta se mostrará en el tbody con ID search-results. Además, mientras carga, se mostrará el GIF de búsqueda que lleva la clase htmx-indicator.

Como véis, de forma muy sencilla podemos tener esa interactividad de las SPA. Adicionalmente esto es muy fácil de implementar en el backend con frameworks minimalistas ya que realmente no usa ninguna tecnología especialmente novedosa por detrás.

Existe muchísimas cosas que se pueden hacer con htmx y un poco de CSS. Podemos cargar diálogos modales así.

Conclusión final

Hemos visto que htmx es tremendamente sencillo pero nos permite realizar muchas cosas para las que la gente usa hoy en día frameworks complejos. Sin embargo, tiene algunas pegas. Este modelo requiere de más coordinación entre el backend y el frontend, ya que ahora no hay API, sino HTML directamente.

Además, en sitios donde la API sea necesaria por otros motivos (aplicaciones móviles) puede significar duplicar parte del trabajo en backend. En cualquier caso, para proyectos pequeños me parece la mejor opción. Además funciona con mucha facilidad con casi cualquier framework web de backend que puedes encontrarte. Y el tema de la autenticación queda completamente manejada por el backend y las cookies de siempre.

¿Vosotros qué pensáis de este framework?

Comentarios

Añadir comentario

Todos los comentarios están sujetos a moderación