## Das Herzstück von [[HTMX]]: Trigger und fortgeschrittene Steuerungstechniken {#sec-f4f92dc347e1} In den bisherigen Artikeln haben wir die grundlegenden Methoden kennengelernt, um mit [[HTMX]] Anfragen an den Server zu senden. Dabei haben wir festgestellt, dass man mit Attributen wie `hx-get`, `hx-post`, `hx-put` und `hx-delete` bereits viele Ajax-Funktionen ohne JavaScripts `fetch()` implementieren kann. Doch wenn man [[HTMX]] verwendet, möchte man oft nicht nur *was* gesendet wird, sondern auch *wann* die Anfrage gesendet wird, steuern. Hier kommt `hx-trigger` ins Spiel. Während `hx-get` oder `hx-post` festlegen, **"was getan werden soll"**, bestimmt `hx-trigger`, **"wann es getan werden soll"**. Ohne `hx-trigger` würde [[HTMX]] lediglich wie ein einfaches Ajax-Tool wirken, das Anfragen nur bei Button-Klicks sendet. Doch erst mit `hx-trigger` beginnt der wahre Reiz von [[HTMX]]. Beispielsweise sind folgende Dinge ohne JavaScript-Code möglich: - Suchanfragen erst nach Beendigung der Eingabe senden - Mehrfachklicks innerhalb kurzer Zeit verhindern - Automatisches Neuladen in regelmäßigen Abständen - Elemente nur laden, wenn sie auf dem Bildschirm sichtbar werden - Anfragen nur unter bestimmten Bedingungen senden - Prioritäten anpassen, um Kollisionen zwischen verschiedenen Anfragen zu vermeiden Anfangs dachte ich auch: "Warum [[HTMX]] nutzen, wenn ein paar Zeilen `fetch()` genügen?" Ich sah [[HTMX]] nur als einfaches Ajax-Tool. Doch meine Einstellung änderte sich komplett, nachdem ich die mächtigen Steuerungsfunktionen von `hx-trigger` erlebt hatte. In diesem Artikel werden wir die **Trigger und fortgeschrittenen Steuerungstechniken** zusammenfassen, die als das wahre Herzstück von [[HTMX]] gelten.  --- ## [[HTMX]] ist mehr als nur ein Button-Tool {#sec-31cdd005939f} Wer [[HTMX]] zum ersten Mal kennenlernt, beginnt meist mit Beispielen wie diesem: ```html
``` Auf den ersten Blick könnte man meinen, [[HTMX]] sei lediglich ein "Tool, das Ajax-Anfragen bei Button-Klicks sendet". Das ist zwar schon sehr praktisch, aber es ist nur ein kleiner Teil dessen, was [[HTMX]] kann. Das wirklich Entscheidende ist, dass man **nicht nur die Anfrage selbst, sondern auch den Zeitpunkt und die Bedingungen für deren Auslösung direkt in HTML deklarieren kann**. Zum Beispiel: - Bei einer Suchleiste ist es eine schlechte UX, bei jedem Tastendruck eine Anfrage an den Server zu senden. Viel natürlicher wäre es, wenn die Anfrage erst 500ms nach Beendigung der Eingabe gesendet wird. - Manchmal möchte man auch, dass ein Button nicht bei einem einfachen Klick, sondern **nur bei einem Klick mit gedrückter Strg-Taste funktioniert**. - Oder man möchte Daten erst dann abrufen, wenn ein bestimmtes Element durch Scrollen auf dem Bildschirm sichtbar wird. Wenn man für solche Fälle jedes Mal JavaScript schreiben müsste, würde der Code schnell unübersichtlich werden. [[HTMX]] hingegen ermöglicht es, diese Steuerungen weitgehend **ohne eine einzige Zeile JavaScript, nur durch die Kombination von Attributen, auszudrücken**. Das ist wirklich erstaunlich. Der Schock, den ich empfand, als ich `hx-trigger` in [[HTMX]] zum ersten Mal sah, war vielleicht vergleichbar mit dem Schock eines C++-Entwicklers, der zum ersten Mal Python-Code sieht und denkt: "Was? Keine Typdeklarationen??" --- ## Standard-Trigger: click, change, submit {#sec-a730147be101} Zunächst ist wichtig zu wissen, dass [[HTMX]] bereits so konzipiert ist, dass es gut mit den Standardverhaltensweisen von HTML-Elementen harmoniert. Beispielsweise sind Buttons standardmäßig mit `click`, Formulare mit `submit` und Eingabeelemente je nach Situation natürlich mit Events wie `change` verknüpft. ```html ``` Dieser Button sendet eine Anfrage bei Klick, auch wenn `hx-trigger="click"` nicht explizit angegeben ist. Das Gleiche gilt für Formulare. ```html ``` In diesem Fall wird die Anfrage beim Absenden des Formulars ausgelöst. Das bedeutet, [[HTMX]] verhält sich in sehr grundlegenden Szenarien bereits recht intelligent. Doch der interessante Teil beginnt hier: **Über die Standardwerte hinauszugehen und den gewünschten Zeitpunkt und die Bedingungen direkt zu deklarieren.** Genau das wollen wir tun. --- ## `hx-trigger`: Häufig verwendete Standardereignisse vs. [[HTMX]]-spezifische Trigger {#sec-8354ed76dc75} Zunächst ist es wichtig, die folgende Tabelle zu verstehen. Der Kernpunkt ist: **Die vom Browser bereitgestellten Standard-DOM-Ereignisse sind selbstverständlich nutzbar + es gibt einige [[HTMX]]-spezifische Trigger.** | Kategorie | Wert | Bedeutung | Häufige Anwendung | Beispiel | | ---------- | ----------------- | ---------------------------- | ----------------------------------- | ---------------------------------------------------------------------- | | Standardereignis | `click` | Bei Klick | Button, Link, Aktionsausführung | `hx-trigger="click"` | | Standardereignis | `input` | Bei jeder Änderung des Eingabewerts | Echtzeitsuche, Autovervollständigung | `hx-trigger="input changed delay:500ms"` | | Standardereignis | `change` | Wenn der Wert endgültig geändert wurde | `select`, `checkbox`, Eingabeübernahme nach Blur | `hx-trigger="change"` | | Standardereignis | `submit` | Bei Formularübermittlung | Formularversand | `hx-trigger="submit"` | | Standardereignis | `keyup` | Beim Loslassen einer Taste | Tastatureingabe-basierte Suche, schnelle Reaktion | `hx-trigger="keyup delay:500ms"` | | Standardereignis | `keydown` | Beim Drücken einer Taste | Hotkeys, Tastaturinteraktion | `hx-trigger="keydown[from:body]"` | | Standardereignis | `mouseup` | Beim Loslassen der Maustaste | Reaktion nach Drag/Auswahl | `hx-trigger="mouseup"` | | [[HTMX]]-spezifisch | `load` | Sobald das Element geladen ist | Verzögertes Laden, initiale Datenfüllung | `hx-trigger="load"` | | [[HTMX]]-spezifisch | `revealed` | Wenn das Element auf dem Bildschirm sichtbar wird | Unendliches Scrollen, Lazy Loading | `hx-trigger="revealed"` | | [[HTMX]]-spezifisch | `intersect` | Wenn das Element den Viewport kreuzt | Präziseres Lazy Loading, Scroll-basiertes Laden | `hx-trigger="intersect once"` | | [[HTMX]]-spezifische Syntax | `every 5s` | In regelmäßigen Abständen | Polling, Statusaktualisierung | `hx-trigger="every 5s"` | | Benutzerdefiniertes Ereignis | `my-custom-event` | Bei selbst definiertem Ereignis | Server-Header, JS-Integration, lose Event-Architektur | `hx-trigger="itemSaved from:body"` | | Modifier | `delay:500ms` | Anfrage nur, wenn innerhalb der angegebenen Zeit keine weiteren Ereignisse auftreten | Debouncing, Optimierung der Echtzeitsuche | `hx-trigger="keyup delay:500ms"` | | Modifier | `throttle:1s` | Begrenzt wiederholte Anfragen innerhalb kurzer Zeit | Schutz vor Mehrfachklicks, Unterdrückung übermäßiger Anfragen | `hx-trigger="click throttle:1s"` | | Modifier | `once` | Begrenzt die Auslösung auf einmal | Erstes Laden, einmaliges Ereignis | `hx-trigger="intersect once"` | | Modifier | `changed` | Anfrage nur, wenn der Wert tatsächlich geändert wurde | Optimierung von Eingabefeldern, Vermeidung unnötiger Anfragen | `hx-trigger="input changed delay:500ms"` | | Modifier | `from:body` | Ziel der Ereigniserkennung auf ein anderes Element festlegen | Globaler Ereignisempfang, benutzerdefinierte Ereignisverarbeitung | `hx-trigger="itemSaved from:body"` | | Modifier | `[condition]` | Anfrage nur, wenn die Bedingung erfüllt ist | Hilfstasten-Kombination, Eingabewertlängenbedingung | `hx-trigger="click[ctrlKey]"` / `hx-trigger="keyup[value.length > 1]"` | | Modifier | `consume` | Verhindert die Weitergabe des Ereignisses an übergeordnete Elemente | Vermeidung von Kollisionen bei verschachtelten [[HTMX]]-Anfragen | `hx-trigger="click consume"` | | Modifier | `queue:first` | Bei Warteschlangenbildung neuer Ereignisse nur das erste beibehalten | Beibehaltung der ersten Anfrage bei kontinuierlicher Eingabe | `hx-trigger="input queue:first"` | | Modifier | `queue:last` | Bei Warteschlangenbildung neuer Ereignisse nur das letzte beibehalten | Suchleiste, Autovervollständigung | `hx-trigger="input queue:last"` | | Modifier | `queue:all` | Alle aufgetretenen Ereignisse in der Warteschlange beibehalten | Wenn alle Ereignisse sequenziell verarbeitet werden müssen | `hx-trigger="input queue:all"` | | Modifier | `queue:none` | Neue Ereignisse ignorieren, wenn eine Anfrage läuft | Komplette Unterdrückung von Duplikatanfragen | `hx-trigger="click queue:none"` | Der `hx-trigger`-Wert setzt sich normalerweise aus einem **Ereignis (event)** zusammen, dem bei Bedarf **Filter** und **Modifier** angehängt werden. Man liest es also in der Reihenfolge: **"Wenn etwas passiert (event), unter welcher Bedingung (filter), und wie soll es verarbeitet werden (modifier)?"** Die Form ist typischerweise `event[filter] modifier modifier`. ```html ``` - `keyup` → Beim Loslassen einer Taste - `[value.length > 1]` → Nur wenn der Eingabewert länger als 1 Zeichen ist - `changed delay:500ms` → Anfrage nur, wenn der Wert geändert wurde und 0,5 Sekunden lang keine weitere Eingabe erfolgt ist ## Einige nützliche Beispiele {#sec-d893c37bc6f7} Obwohl die obige Tabelle bereits eine gute Übersicht bietet, möchte ich Ihnen noch einige meiner bevorzugten Trigger-Beispiele vorstellen. ### Anfragen nur nach Beendigung der Eingabe: `delay` {#sec-cd31c7256394} Beim Erstellen von Funktionen wie der automatischen Vervollständigung in Suchfeldern oder Echtzeitfilterung kann das Senden einer Anfrage bei jedem Tastendruck des Benutzers den Server belasten und die Benutzererfahrung als unruhig empfunden werden. Hier sorgt `delay` für ein viel flüssigeres Erlebnis. ```html ``` Dieser Code sendet nicht sofort eine Anfrage, sobald der Benutzer eine Taste drückt. Stattdessen wird die Anfrage **erst 500ms nach Beendigung der Eingabe** gesendet. Dies ist im Wesentlichen **Debouncing**. Um dies mit JavaScript zu implementieren, müsste man einen Timer setzen, den vorherigen Timer abbrechen und einen neuen setzen. Mit [[HTMX]] erledigt man das einfach über ein Attribut. Bei Such-, Auto-Vervollständigungs- und Filter-UIs ist diese Funktion fast schon Standard. --- ### Nicht zu oft senden: `throttle` {#sec-c84ae134ee88} Während sich `delay` so anfühlt, als würde man "nach Beendigung der Eingabe kurz warten und dann senden", zielt `throttle` eher darauf ab, "zu häufige Anfragen innerhalb kurzer Zeit zu begrenzen". ```html ``` In diesem Fall kann man steuern, dass selbst bei sehr schnellem, wiederholtem Drücken des Buttons innerhalb einer Sekunde keine übermäßigen Anfragen aufeinanderfolgend gesendet werden. Dies ist in folgenden Situationen sehr nützlich: - Verhinderung von Mehrfachklicks - Blockieren zu schneller, wiederholter Anfragen - Reduzierung der Serverlast - Verhindern, dass versehentlich dieselbe Aktion mehrmals ausgeführt wird Besonders bei Buttons wie "Gefällt mir", "Speichern", "Aktualisieren" oder "Synchronisieren" sollte man dies in Betracht ziehen. --- ### Automatische Anfragen in regelmäßigen Abständen: `every` {#sec-0195e4e0d263} Eine überraschend attraktive Funktion von [[HTMX]] ist `every`. Wenn Sie einen bestimmten Bereich in regelmäßigen Abständen vom Server neu laden möchten, müssen Sie keine separate Polling-Logik in JavaScript schreiben. ```html