## El corazón de HTMX: Triggers y técnicas de control avanzadas {#sec-f4f92dc347e1} En los artículos anteriores, exploramos los métodos básicos para enviar solicitudes al servidor con [[HTMX]]. Hemos comprobado que propiedades como `hx-get`, `hx-post`, `hx-put` y `hx-delete` permiten implementar una gran cantidad de funcionalidades Ajax sin necesidad de `fetch()` de JavaScript. Sin embargo, al usar HTMX, a menudo deseamos controlar **cuándo se envía una solicitud**, más que simplemente enviarla. Aquí es donde entra en juego `hx-trigger`. Si `hx-get` o `hx-post` definen **"qué hacer"**, `hx-trigger` define **"cuándo hacerlo"**. Sin `hx-trigger`, HTMX podría parecer una herramienta Ajax sencilla que solo envía solicitudes al hacer clic en un botón. Pero es con el uso de `hx-trigger` que la satisfacción al trabajar con HTMX realmente comienza a crecer. Por ejemplo, las siguientes acciones son posibles sin código JavaScript: - Enviar una solicitud de búsqueda solo después de que el usuario haya dejado de escribir. - Evitar clics duplicados en un corto periodo de tiempo. - Actualizar automáticamente a intervalos regulares. - Cargar contenido solo cuando un elemento aparece en pantalla. - Enviar solicitudes solo bajo ciertas condiciones. - Ajustar la prioridad para evitar conflictos entre diferentes solicitudes. Al principio, pensaba: "¿Por qué usar [[HTMX]] si puedo lograr lo mismo con unas pocas líneas de `fetch()`?". Mi percepción de HTMX como una simple herramienta Ajax cambió por completo después de experimentar el potente control que ofrece `hx-trigger`. En este artículo, vamos a explorar y organizar los **triggers y técnicas de control avanzadas**, que son la verdadera esencia de HTMX.  --- ## [[HTMX]] no es solo una herramienta de botones {#sec-31cdd005939f} Cuando uno se acerca a HTMX por primera vez, a menudo empieza con ejemplos como este: ```html
``` Con esto, HTMX puede parecer simplemente una "herramienta para enviar solicitudes Ajax al pulsar un botón". Claro, eso ya es bastante útil. Pero es solo una parte de lo que HTMX puede hacer. Lo verdaderamente importante es que **se pueden declarar el momento y las condiciones en que se produce una solicitud directamente en el HTML**. Por ejemplo: - Enviar una solicitud al servidor con cada pulsación en un campo de búsqueda es la peor experiencia de usuario. En cambio, si la solicitud se envía 500ms después de que la entrada se detiene, la experiencia es mucho más fluida. - Quizás quieras que un botón funcione solo cuando se **hace clic mientras se mantiene pulsada la tecla Ctrl**. - O tal vez desees cargar datos solo cuando un elemento específico se hace visible al desplazar la página. Si tuvieras que escribir JavaScript para cada una de estas situaciones, el código crecería rápidamente. Sin embargo, HTMX permite expresar gran parte de este control **combinando atributos, sin una sola línea de JavaScript**. Esto es realmente sorprendente. La impresión que tuve al ver `hx-trigger` de HTMX fue similar al shock de un desarrollador de C++ al ver código Python por primera vez y pensar: "¿Qué? ¿No hay declaración de tipos?". --- ## Triggers básicos: click, change, submit {#sec-a730147be101} Lo primero que hay que saber es que [[HTMX]] está diseñado para funcionar bien con el comportamiento predeterminado de los elementos HTML. Por ejemplo, un botón se conecta de forma natural al evento `click`, un formulario al evento `submit`, y los elementos de entrada a eventos como `change` según la situación. ```html ``` Este botón enviará una solicitud al hacer clic, incluso sin `hx-trigger="click"`. Lo mismo ocurre con los formularios: ```html ``` En este caso, la solicitud se produce al enviar el formulario. En resumen, HTMX funciona de manera bastante inteligente en escenarios muy básicos. Pero la parte que nos interesa comienza aquí: **Ir más allá de los valores predeterminados y declarar directamente el momento y las condiciones que deseamos.** Esto es lo que queremos lograr. --- ## Eventos estándar de uso frecuente vs. Triggers exclusivos de [[HTMX]] en `hx-trigger` {#sec-8354ed76dc75} En primer lugar, es crucial dominar la siguiente tabla. La clave es que **los eventos estándar del DOM que proporciona el navegador son, por supuesto, utilizables, además de algunos triggers exclusivos de HTMX.** | Categoría | Valor | Significado | Casos de uso comunes | Ejemplo | | ---------- | ----------------- | ---------------------------- | ----------------------------------- | ---------------------------------------------------------------------- | | Evento estándar | `click` | Solicitud al hacer clic | Botones, enlaces, ejecución de acciones | `hx-trigger="click"` | | Evento estándar | `input` | Solicitud cada vez que cambia el valor de entrada | Búsqueda en tiempo real, autocompletado | `hx-trigger="input changed delay:500ms"` | | Evento estándar | `change` | Solicitud cuando el valor cambia y se confirma | `select`, `checkbox`, actualización de entrada después de blur | `hx-trigger="change"` | | Evento estándar | `submit` | Solicitud al enviar un formulario | Envío de formularios | `hx-trigger="submit"` | | Evento estándar | `keyup` | Solicitud al soltar una tecla | Búsqueda basada en teclado, reacciones rápidas | `hx-trigger="keyup delay:500ms"` | | Evento estándar | `keydown` | Solicitud al pulsar una tecla | Hotkeys, interacción de teclado | `hx-trigger="keydown[from:body]"` | | Evento estándar | `mouseup` | Solicitud al soltar el botón del ratón | Reacción después de arrastrar/seleccionar | `hx-trigger="mouseup"` | | Exclusivo de htmx | `load` | Solicitud tan pronto como el elemento se carga | Carga diferida, precarga de datos iniciales | `hx-trigger="load"` | | Exclusivo de htmx | `revealed` | Solicitud cuando el elemento se hace visible en pantalla | Scroll infinito, lazy loading | `hx-trigger="revealed"` | | Exclusivo de htmx | `intersect` | Solicitud cuando el elemento cruza el viewport | Lazy loading más preciso, carga basada en scroll | `hx-trigger="intersect once"` | | Sintaxis htmx | `every 5s` | Solicitud a intervalos regulares | Polling, actualización de estado | `hx-trigger="every 5s"` | | Evento personalizado | `my-custom-event` | Solicitud con un evento definido por el usuario | Encabezados de servidor, integración JS, arquitectura de eventos desacoplada | `hx-trigger="itemSaved from:body"` | | Modificador | `delay:500ms` | Solicitud solo si no hay eventos adicionales durante el tiempo especificado | Debouncing, optimización de búsqueda en tiempo real | `hx-trigger="keyup delay:500ms"` | | Modificador | `throttle:1s` | Limita las solicitudes repetidas en un corto periodo de tiempo | Prevención de clics duplicados, supresión de solicitudes excesivas | `hx-trigger="click throttle:1s"` | | Modificador | `once` | Limita el trigger a una sola vez | Carga inicial, eventos únicos | `hx-trigger="intersect once"` | | Modificador | `changed` | Solicitud solo si el valor ha cambiado realmente | Optimización de campos de entrada, prevención de solicitudes innecesarias | `hx-trigger="input changed delay:500ms"` | | Modificador | `from:body` | Especifica un elemento diferente para la detección de eventos | Recepción de eventos globales, manejo de eventos personalizados | `hx-trigger="itemSaved from:body"` | | Modificador | `[condition]` | Solicitud solo si se cumple la condición | Combinación de teclas modificadoras, condición de longitud de entrada | `hx-trigger="click[ctrlKey]"` / `hx-trigger="keyup[value.length > 1]"` | | Modificador | `consume` | Evita que el evento se propague a elementos superiores (padres) | Prevención de conflictos de solicitudes htmx anidadas | `hx-trigger="click consume"` | | Modificador | `queue:first` | Mantiene solo el primer evento al encolar nuevos eventos | Mantener solo la solicitud inicial durante entradas continuas | `hx-trigger="input queue:first"` | | Modificador | `queue:last` | Mantiene solo el último evento al encolar nuevos eventos | Campo de búsqueda, autocompletado | `hx-trigger="input queue:last"` | | Modificador | `queue:all` | Mantiene todos los eventos en la cola | Cuando todos los eventos deben procesarse secuencialmente | `hx-trigger="input queue:all"` | | Modificador | `queue:none` | Ignora nuevos eventos si hay una solicitud en curso | Bloqueo total de solicitudes duplicadas | `hx-trigger="click queue:none"` | El valor de `hx-trigger` suele comenzar con un **evento (event)**, y si es necesario, se le añaden **filtros (filter)** y **modificadores (modifier)**. Así, se lee como **“cuando ocurre algo (event), bajo qué condición (filter), y de qué manera se procesa (modifier)”**. La forma común es `event[filter] modifier modifier`. ```html ``` - `keyup` → al soltar una tecla - `[value.length > 1]` → solo si el valor de entrada tiene más de 1 carácter - `changed delay:500ms` → la solicitud se envía solo si el valor ha cambiado y no hay entradas adicionales durante 0.5 segundos. ## Algunos ejemplos útiles {#sec-d893c37bc6f7} Aunque la tabla anterior lo resume bien, no quiero terminar sin mostrar algunos de mis ejemplos de triggers favoritos. ### Solicitar solo después de que la entrada se detenga: `delay` {#sec-cd31c7256394} Al crear funciones como autocompletado en un campo de búsqueda o filtrado en tiempo real, enviar una solicitud cada vez que el usuario escribe puede sobrecargar el servidor y generar una experiencia de usuario algo impaciente. En estos casos, usar `delay` hace que la interacción sea mucho más fluida. ```html ``` Este código no envía una solicitud inmediatamente cada vez que el usuario presiona una tecla. En cambio, **espera 500ms después de que la entrada se detiene** para enviar la solicitud. Esto es, de hecho, un **debouncing**. Para implementarlo en JavaScript, se necesitaría código para establecer un temporizador, cancelar el temporizador anterior y volver a configurarlo. Pero con [[HTMX]], se logra simplemente con un atributo. Esta funcionalidad es prácticamente un estándar en interfaces de búsqueda, sugerencias automáticas y filtrado. --- ### No enviar con demasiada frecuencia: `throttle` {#sec-c84ae134ee88} Mientras que `delay` significa "esperar un momento después de que la entrada se detenga antes de enviar", `throttle` se enfoca en "limitar el envío demasiado frecuente en un corto periodo de tiempo". ```html ``` En este caso, incluso si el usuario hace clic en el botón muy rápidamente varias veces, se puede controlar para que las solicitudes no se envíen de forma excesiva y continua en un intervalo de 1 segundo. Es bastante útil en situaciones como: - Prevención de clics duplicados. - Bloqueo de solicitudes repetidas demasiado rápidas. - Reducción de la carga del servidor. - Evitar la ejecución accidental de la misma acción varias veces. Especialmente para botones como "Me gusta", "Guardar", "Actualizar" o "Sincronizar", es una consideración que vale la pena tener en cuenta. --- ### Solicitar automáticamente a intervalos regulares: `every` {#sec-0195e4e0d263} Al usar [[HTMX]], una característica sorprendentemente atractiva es `every`. Cuando se desea actualizar un área específica del servidor a intervalos regulares, no es necesario escribir una lógica de polling separada en JavaScript. ```html