## Le cœur de HTMX : les déclencheurs et les techniques de contrôle avancées {#sec-f4f92dc347e1} Dans les articles précédents, nous avons exploré les méthodes de base pour envoyer des requêtes au serveur avec [[HTMX]]. Nous avons constaté qu'en utilisant des attributs comme `hx-get`, `hx-post`, `hx-put` et `hx-delete`, il est possible d'implémenter un grand nombre d'opérations Ajax sans avoir recours à la fonction `fetch()` de JavaScript. Cependant, en utilisant HTMX, on souhaite souvent contrôler **non pas tant l'envoi de la requête que le moment où elle est envoyée**. C'est là qu'intervient `hx-trigger`. Si `hx-get` ou `hx-post` définissent **« ce qu'il faut faire »**, `hx-trigger` détermine **« quand le faire »**. Sans `hx-trigger`, HTMX pourrait sembler être un simple outil Ajax qui envoie des requêtes uniquement lors d'un clic sur un bouton. Mais c'est avec l'utilisation de `hx-trigger` que la satisfaction d'utiliser HTMX commence vraiment à monter. Par exemple, les actions suivantes deviennent possibles sans une seule ligne de code JavaScript : - Envoyer une requête de recherche uniquement après l'arrêt de la saisie. - Empêcher les clics multiples en peu de temps. - Actualiser automatiquement à intervalles réguliers. - Charger un élément uniquement lorsqu'il apparaît à l'écran. - Envoyer une requête uniquement sous certaines conditions. - Ajuster la priorité pour éviter les conflits entre différentes requêtes. Au début, je me disais : « Pourquoi utiliser [[HTMX]] quand quelques lignes de `fetch` suffiraient ? » et je ne voyais HTMX que comme un simple outil Ajax. Mais après avoir expérimenté les puissantes capacités de contrôle de `hx-trigger`, mon attitude a complètement changé. Dans cet article, nous allons passer en revue les **déclencheurs et les techniques de contrôle avancées**, qui peuvent être considérés comme le véritable cœur de HTMX.  --- ## [[HTMX]] n'est pas qu'un simple outil pour boutons {#sec-31cdd005939f} Lorsque l'on découvre HTMX, on commence généralement par un exemple comme celui-ci : ```html
``` À première vue, HTMX peut sembler être un simple « outil qui envoie des requêtes Ajax quand on clique sur un bouton ». Bien sûr, c'est déjà très pratique. Mais ce n'est qu'une partie de ce que HTMX peut faire. Ce qui est vraiment important, c'est la capacité de **déclarer le moment et les conditions de déclenchement de la requête directement en HTML**. Par exemple : - Envoyer une requête au serveur à chaque frappe dans une barre de recherche est une très mauvaise expérience utilisateur. Par contre, si la requête n'est envoyée que 500 ms après l'arrêt de la saisie, l'expérience sera bien plus fluide. - Certains boutons peuvent être conçus pour ne fonctionner que si l'on clique dessus **tout en maintenant la touche Ctrl enfoncée**. - Ou encore, on peut souhaiter charger des données uniquement lorsqu'un élément spécifique devient visible à l'écran après un défilement. Si vous deviez écrire du JavaScript à chaque fois pour gérer ces situations, votre code grossirait rapidement. En revanche, HTMX permet d'exprimer une grande partie de ce contrôle **en combinant des attributs, sans une seule ligne de JavaScript**. C'est vraiment étonnant. Le choc que j'ai ressenti en découvrant `hx-trigger` de HTMX est comparable à celui d'un développeur C++ découvrant le code Python et se disant : « Quoi ? Pas de déclaration de type ?? ». --- ## Déclencheurs de base : click, change, submit {#sec-a730147be101} La première chose à savoir est que [[HTMX]] est conçu pour bien s'intégrer aux comportements HTML par défaut. Par exemple, un bouton est naturellement associé à l'événement `click`, Un formulaire à l'événement `submit`, Et un élément de saisie aux événements comme `change` selon le contexte. ```html ``` Ce bouton envoie une requête au clic, sans qu'il soit nécessaire d'ajouter explicitement `hx-trigger="click"`. Il en va de même pour les formulaires : ```html ``` Dans ce cas, la requête est déclenchée lors de la soumission du formulaire. En d'autres termes, HTMX fonctionne de manière assez intelligente pour les scénarios très basiques. Mais c'est à partir de là que notre intérêt doit se porter. **Déclarer directement les moments et les conditions souhaitées, au-delà des valeurs par défaut.** C'est précisément ce que nous voulons faire. --- ## Événements standards couramment utilisés avec `hx-trigger` vs déclencheurs spécifiques à [[HTMX]] {#sec-8354ed76dc75} Il est essentiel de maîtriser le tableau ci-dessous. Le point clé est que **les événements DOM standards fournis par le navigateur sont bien sûr utilisables, et il existe en plus quelques déclencheurs spécifiques à HTMX**. | Catégorie | Valeur | Signification | Situations fréquentes | Exemple | | ---------- | ----------------- | ---------------------------- | ----------------------------------- | ---------------------------------------------------------------------- | | Événement standard | `click` | Requête au clic | Boutons, liens, exécution d'actions | `hx-trigger="click"` | | Événement standard | `input` | Requête à chaque modification de la valeur d'entrée | Recherche en temps réel, auto-complétion | `hx-trigger="input changed delay:500ms"` | | Événement standard | `change` | Requête lorsque la valeur est confirmée et modifiée | `select`, `checkbox`, saisie après blur | `hx-trigger="change"` | | Événement standard | `submit` | Requête à la soumission du formulaire | Soumission de formulaire | `hx-trigger="submit"` | | Événement standard | `keyup` | Requête au relâchement d'une touche | Recherche basée sur la frappe, réactions rapides | `hx-trigger="keyup delay:500ms"` | | Événement standard | `keydown` | Requête à l'appui d'une touche | Raccourcis clavier, interactions au clavier | `hx-trigger="keydown[from:body]"` | | Événement standard | `mouseup` | Requête au relâchement du bouton de la souris | Réaction après glisser/sélection | `hx-trigger="mouseup"` | | Spécifique à htmx | `load` | Requête dès le chargement de l'élément | Chargement différé, remplissage de données initiales | `hx-trigger="load"` | | Spécifique à htmx | `revealed` | Requête lorsque l'élément apparaît à l'écran | Défilement infini, lazy loading | `hx-trigger="revealed"` | | Spécifique à htmx | `intersect` | Requête lorsque l'élément croise la fenêtre d'affichage | Lazy loading plus précis, chargement basé sur le défilement | `hx-trigger="intersect once"` | | Syntaxe htmx spécifique | `every 5s` | Requête à intervalles réguliers | Polling, mise à jour de l'état | `hx-trigger="every 5s"` | | Événement personnalisé | `my-custom-event` | Requête avec un événement défini par l'utilisateur | En-têtes de serveur, intégration JS, architecture d'événements souple | `hx-trigger="itemSaved from:body"` | | Modificateur | `delay:500ms` | Requête uniquement s'il n'y a pas d'événement supplémentaire pendant le temps spécifié | Débouncing, optimisation de la recherche en temps réel | `hx-trigger="keyup delay:500ms"` | | Modificateur | `throttle:1s` | Limite les requêtes répétées sur une courte période | Prévention des clics multiples, suppression des requêtes excessives | `hx-trigger="click throttle:1s"` | | Modificateur | `once` | Limite le déclenchement à une seule fois | Chargement initial, événement unique | `hx-trigger="intersect once"` | | Modificateur | `changed` | Requête uniquement si la valeur a réellement changé | Optimisation des champs de saisie, prévention des requêtes inutiles | `hx-trigger="input changed delay:500ms"` | | Modificateur | `from:body` | Spécifie une autre cible pour la détection de l'événement | Réception d'événements globaux, traitement d'événements personnalisés | `hx-trigger="itemSaved from:body"` | | Modificateur | `[condition]` | Requête uniquement si la condition est remplie | Combinaisons de touches auxiliaires, condition de longueur de saisie | `hx-trigger="click[ctrlKey]"` / `hx-trigger="keyup[value.length > 1]"` | | Modificateur | `consume` | Empêche la propagation de l'événement aux éléments parents ou supérieurs | Prévention des conflits de requêtes htmx imbriquées | `hx-trigger="click consume"` | | Modificateur | `queue:first` | Lors de la mise en file d'attente de nouveaux événements, ne conserve que le premier | Maintenir uniquement la première requête lors de saisies continues | `hx-trigger="input queue:first"` | | Modificateur | `queue:last` | Lors de la mise en file d'attente de nouveaux événements, ne conserve que le dernier | Barre de recherche, auto-complétion | `hx-trigger="input queue:last"` | | Modificateur | `queue:all` | Conserve tous les événements en file d'attente | Lorsque tous les événements doivent être traités séquentiellement | `hx-trigger="input queue:all"` | | Modificateur | `queue:none` | Ignore les nouveaux événements si une requête est en cours | Blocage complet des requêtes en double | `hx-trigger="click queue:none"` | La valeur de `hx-trigger` commence généralement par un **événement**, puis, si nécessaire, des **filtres** et des **modificateurs** sont ajoutés pour la combiner. Autrement dit, on peut la lire dans l'ordre suivant : **« quand quelque chose se produit (événement), sous quelles conditions (filtre), et de quelle manière (modificateur) »**. La forme est généralement `event[filter] modifier modifier`. ```html ``` - `keyup` → Au relâchement d'une touche - `[value.length > 1]` → Uniquement si la valeur de saisie est supérieure à 1 caractère - `changed delay:500ms` → Requête uniquement si la valeur a changé et qu'il n'y a pas eu de saisie supplémentaire pendant 0,5 seconde ## Quelques exemples utiles {#sec-d893c37bc6f7} Bien que le tableau ci-dessus résume les informations, il serait dommage de s'arrêter là. Je vais vous montrer quelques-uns de mes exemples de déclencheurs préférés. ### Envoyer une requête uniquement après l'arrêt de la saisie : `delay` {#sec-cd31c7256394} Lors de la création de fonctionnalités telles que l'auto-complétion de la barre de recherche ou le filtrage en temps réel, l'envoi d'une requête à chaque frappe de l'utilisateur peut surcharger le serveur et rendre l'expérience utilisateur quelque peu précipitée. Dans ces cas, l'utilisation de `delay` rend l'expérience beaucoup plus fluide. ```html ``` Ce code n'envoie pas de requête immédiatement à chaque frappe de l'utilisateur. Au lieu de cela, il envoie une requête **500 ms après l'arrêt de la saisie**. C'est en fait du **débouncing**. Pour l'implémenter en JavaScript, il faudrait du code pour gérer un minuteur, annuler le minuteur précédent et en définir un nouveau. Mais avec [[HTMX]], c'est réglé avec un simple attribut. Cette fonctionnalité est presque indispensable pour les interfaces utilisateur de recherche, de suggestion automatique et de filtrage. --- ### Éviter les envois trop fréquents : `throttle` {#sec-c84ae134ee88} Si `delay` donne l'impression d'« attendre un instant après l'arrêt de la saisie avant d'envoyer », `throttle` est plus axé sur la « limitation des envois trop fréquents sur une courte période ». ```html ``` Dans ce cas, même si l'utilisateur clique très rapidement plusieurs fois sur le bouton, vous pouvez contrôler que les requêtes ne soient pas envoyées de manière excessive et consécutive en moins d'une seconde. C'est très utile dans les situations suivantes : - Prévention des clics multiples - Blocage des requêtes répétées trop rapides - Réduction de la charge du serveur - Prévention de l'exécution accidentelle de la même action plusieurs fois C'est particulièrement pertinent pour des boutons comme « J'aime », « Enregistrer », « Actualiser » ou « Synchroniser ». --- ### Requêtes automatiques à intervalles réguliers : `every` {#sec-0195e4e0d263} En utilisant [[HTMX]], la fonctionnalité `every` est étonnamment attrayante. Lorsque vous souhaitez actualiser une zone spécifique du serveur à intervalles réguliers, vous n'avez pas besoin d'écrire une logique de polling distincte en JavaScript. ```html