Le cœur de HTMX : les déclencheurs et les techniques de contrôle avancées
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
Lorsque l'on découvre HTMX, on commence généralement par un exemple comme celui-ci :
<button hx-get="/hello/" hx-target="#result">
불러오기
</button>
<div id="result"></div>
À 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
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.
<button hx-get="/load/" hx-target="#result">
가져오기
</button>
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 :
<form hx-post="/submit/" hx-target="#result">
<input type="text" name="title">
<button type="submit">전송</button>
</form>
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
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.
<input
hx-get="/search/"
hx-trigger="keyup[value.length > 1] changed delay:500ms">
keyup→ Au relâchement d'une touche[value.length > 1]→ Uniquement si la valeur de saisie est supérieure à 1 caractèrechanged 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
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
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.
<input type="text"
name="q"
hx-get="/search/"
hx-trigger="keyup delay:500ms"
hx-target="#search-result"
placeholder="검색어를 입력하세요">
<div id="search-result"></div>
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
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 ».
<button hx-post="/like/"
hx-trigger="click throttle:1s"
hx-target="#like-count">
좋아요
</button>
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
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.
<div hx-get="/server-status/"
hx-trigger="every 5s"
hx-target="this">
서버 상태를 불러오는 중...
</div>
Ce code envoie une requête GET à /server-status/ toutes les 5 secondes et met à jour l'élément lui-même avec la réponse.
Les cas d'utilisation sont plus nombreux qu'on ne le pense :
- Surveillance de l'état du serveur
- Affichage de la progression des tâches
- Mise à jour des chiffres du tableau de bord
- Mise à jour du nombre de notifications de chat
- Affichage d'informations simples en temps réel sur un écran d'administration
Bien sûr, il faut faire attention à ne pas en abuser avec des intervalles trop courts, car cela pourrait surcharger le serveur. Mais utilisée à bon escient, la capacité de résoudre une telle fonctionnalité avec de simples attributs HTML est l'un des charmes de HTMX.
Activer uniquement sous certaines conditions : le filtrage d'événements
La fonctionnalité de filtrage d'événements est vraiment excellente. Lorsque je l'ai découverte pour la première fois, j'ai ressenti une grande gratitude envers les développeurs et contributeurs de HTMX. C'est formidable.
Avec HTMX, vous pouvez ajouter des conditions après un événement pour restreindre les requêtes à des situations spécifiques.
<button hx-delete="/post/123/"
hx-trigger="click[ctrlKey]"
hx-target="#post-123"
hx-swap="outerHTML">
삭제
</button>
Ce code ne fonctionnera pas avec un simple clic. La requête de suppression ne sera déclenchée que si vous cliquez en maintenant la touche Ctrl enfoncée.
Ce type de déclencheur conditionnel est un petit détail qui peut rendre l'expérience utilisateur beaucoup plus raffinée.
Par exemple :
- Exécuter uniquement lorsqu'une touche auxiliaire spécifique est enfoncée
- Exécuter uniquement si une case à cocher est sélectionnée
- Rechercher uniquement si la valeur de saisie dépasse une certaine longueur
- Ne pas envoyer de requête si la chaîne est vide
Peut être étendu à des flux similaires.
<input type="text"
name="q"
hx-get="/search/"
hx-trigger="keyup[value.length > 1] delay:400ms"
hx-target="#result">
De cette façon, vous pouvez faire en sorte que la requête ne soit envoyée que si le terme de recherche contient au moins deux caractères.
load : Exécuter dès le chargement de la page ou de l'élément
Il arrive que l'on veuille remplir certaines zones de données dès l'ouverture de la page. Par exemple, les statistiques du tableau de bord, les listes de recommandations ou les zones de notification.
Dans ce cas, vous pouvez utiliser load.
<div hx-get="/dashboard/summary/"
hx-trigger="load"
hx-target="this">
요약 정보를 불러오는 중...
</div>
Ce code envoie une requête dès que l'élément est chargé et remplace ou met à jour l'élément lui-même avec la réponse.
Il peut également être utilisé pour charger certaines zones relativement lourdes plus tard, au lieu de rendre toute la page côté serveur. C'est-à-dire qu'il s'adapte bien aux simples schémas de chargement différé.
revealed : Exécuter quand l'élément apparaît à l'écran
Ce déclencheur a un nom très intuitif. Il envoie une requête lorsque l'élément apparaît à l'écran.
<div hx-get="/posts/next-page/"
hx-trigger="revealed"
hx-swap="afterend">
더 많은 글을 불러오는 중...
</div>
Cette méthode est couramment utilisée pour implémenter le défilement infini.
Lorsque l'utilisateur fait défiler la page vers le bas et que l'élément devient visible, le bloc de données suivant est chargé et ajouté à la suite. C'est très attrayant car cela permet d'implémenter un défilement infini assez fluide sans avoir à manipuler directement l'Intersection Observer en JavaScript.
Cependant, revealed est simple et pratique, mais peut sembler insuffisant lorsque un contrôle très fin est nécessaire. Dans ce cas, intersect est plus approprié.
intersect : Gérer l'intersection avec la fenêtre d'affichage de manière plus précise
Si revealed est plus proche de la notion de « est-ce visible ? », intersect gère de manière plus précise dans quelle mesure et à quel moment un élément croise la fenêtre d'affichage.
<div hx-get="/analytics/block/"
hx-trigger="intersect once"
hx-target="this">
분석 영역 로딩 중...
</div>
Dans cet exemple, une requête est envoyée une seule fois au moment où l'élément croise la fenêtre d'affichage.
Cette approche est idéale dans les cas suivants :
- Charger des sections lourdes plus tard sur une longue page
- Enregistrer le moment de l'affichage d'une publicité/bannière
- Charger des données uniquement lorsqu'une zone spécifique est réellement visible
- Remplir le contenu progressivement en fonction du défilement
C'est une fonctionnalité que l'on est amené à utiliser au moins une fois pour le défilement infini, le lazy loading et les écrans où l'optimisation des performances est cruciale.
Dialogue entre serveur et client : l'en-tête HX-Trigger
En utilisant HTMX, on atteint un point où l'envoi de requêtes par le navigateur seul ne suffit plus. Le moment vient où l'on souhaite que d'autres éléments de l'interface utilisateur réagissent également après la fin de la réponse du serveur.
Par exemple, dans les situations suivantes :
- Je veux recharger la liste une fois l'enregistrement terminé.
- Je veux afficher un message de succès après l'enregistrement.
- Je veux mettre à jour le nombre du compteur en même temps.
Bien que tout cela puisse être regroupé côté client avec JavaScript, HTMX permet au serveur de déclencher des événements via des en-têtes.
Par exemple, dans une vue Django :
from django.http import HttpResponse
import json
def save_item(request):
response = HttpResponse("<div>저장 완료</div>")
response["HX-Trigger"] = json.dumps({
"itemSaved": {
"message": "저장이 완료되었습니다."
}
})
return response
Ensuite, côté client, ces événements peuvent être utilisés :
<div hx-get="/items/list/"
hx-trigger="itemSaved from:body"
hx-target="#item-list">
</div>
<div hx-get="/toast/success/"
hx-trigger="itemSaved from:body"
hx-target="#toast-area">
</div>
L'avantage de cette structure est clair.
Le serveur, après avoir traité la requête d'enregistrement, n'envoie pas seulement un « HTML d'enregistrement terminé », mais peut également envoyer des signaux pour des réactions ultérieures, tels que « maintenant, mets à jour la liste » ou « affiche une notification ».
En d'autres termes, le serveur et le client communiquent au-delà d'une simple relation requête-réponse, en utilisant une structure événementielle plus souple.
Cela peut sembler insignifiant au début, mais à mesure que l'interface utilisateur s'agrandit, ce modèle devient de plus en plus puissant.
Conclusion
Dans cet article, nous avons passé en revue les attributs de contrôle clés de HTMX, en nous concentrant sur les fonctionnalités avancées centrées sur hx-trigger.
En résumé, voici les points essentiels :
hx-triggerdétermine quand une requête doit être déclenchée.- L'attribut trigger inclut des ÉVÉNEMENTS DOM de navigateur standard et des ÉVÉNEMENTS spécifiques à HTMX.
- Les déclencheurs conditionnels permettent de déclencher des requêtes uniquement dans des situations spécifiques.
- Les attributs modificateurs permettent d'ajuster finement les événements.
- L'en-tête
HX-Triggerpermet au serveur de déclencher des actions ultérieures côté client.
C'est à peu près tout ce que je peux résumer pour cet article.
Le fait que tout cela soit possible sans une seule ligne de JavaScript est vraiment appréciable. Pour être précis, il faudrait dire « sans une seule ligne de JavaScript que j'ai écrite », car le code JavaScript chargé via le CDN s'exécute déjà dans le navigateur.
Articles connexes :
- Simplifier le développement web dynamique avec Django et HTMX (Partie 1)
- Simplifier le développement web dynamique avec Django et HTMX - Ajax (Partie 2)
- Simplifier le développement web dynamique avec Django et HTMX (Partie 3) : Intégration avec Django
- Simplifier le développement web dynamique avec Django et HTMX (Partie 4) : Les méthodes d'envoi de la charge utile (payload)
- Simplifier le développement web dynamique avec Django et HTMX : Utilisation des Forms et des Serializers
Aucun commentaire.