htmx Tutorial · Making Requests · Lesson 6 of 30

Triggers: hx-trigger

Choose which event sends the request: clicks, typing with a delay, page load, scrolling into view, keyboard filters and polling.

Create a free account to save this page, take notes and track your progress. Sign in

Default triggers

Without hx-trigger, htmx uses the natural event for each element:

Element Default trigger
<input>, <textarea>, <select> change
<form> submit
everything else click

Choosing the event

hx-trigger takes any DOM event name: hx-trigger="mouseenter", hx-trigger="keyup", hx-trigger="dblclick". Separate several with commas: hx-trigger="click, keyup[key=='Enter']".

Modifiers

Modifier Meaning
once trigger only the first time
changed only if the element's value has changed
delay:500ms wait until events stop for 500 ms, then send (debounce)
throttle:1s send at most once per second
from:<selector> listen for the event on another element, e.g. from:body
Debounce with delay, run once with onceTry it yourself
<input name="q" placeholder="Type, then pause..." hx-get="/count" hx-target="#typed"
       hx-trigger="input changed delay:500ms">
<p id="typed">Requests are sent only when you pause.</p>
<button hx-get="/once" hx-trigger="click once" hx-target="#once-out">Only works once</button>
<span id="once-out"></span>

<!-- The pretend server: on a real site this part is your backend (Python, PHP, Node, Go...) -->
<script>
  server.get("/count", (req) => `You typed <strong>${server.escape(req.query.q)}</strong> (${(req.query.q || "").length} characters)`);
  server.get("/once", () => "Done. Click again: nothing is sent.");
</script>

Special triggers

Trigger Fires
load when the element is loaded into the page (lazy loading)
revealed when the element scrolls into the viewport (infinite scroll)
intersect like revealed, with options such as threshold:0.5
every 2s on a timer (polling)

Events can also have a filter in square brackets, a JavaScript expression: keyup[key=='Enter'] or click[ctrlKey].

load, every and a key filterTry it yourself
<div hx-get="/news" hx-trigger="load">Loading the news...</div>
<p>Server time (updates every 2 seconds):
  <strong hx-get="/clock" hx-trigger="load, every 2s">...</strong></p>
<input placeholder="Press Enter to send" name="msg" hx-post="/send" hx-trigger="keyup[key=='Enter']" hx-target="#sent">
<p id="sent"></p>

<!-- The pretend server: on a real site this part is your backend (Python, PHP, Node, Go...) -->
<script>
  server.get("/news", () => "<p><strong>News:</strong> htmx 2.0.11 is out.</p>", { delay: 800 });
  server.get("/clock", () => new Date().toLocaleTimeString());
  server.post("/send", (req) => "Sent: " + server.escape(req.body.msg));
</script>

Test yourself

Which hx-trigger value sends a search request only after the user stops typing for half a second?

  1. input changed delay:500ms
  2. input throttle:500ms
  3. every 500ms
  4. load delay:500ms
Show answer

Answer: input changed delay:500ms

delay waits until events stop (debounce); changed skips requests when the value is the same.

Was this page helpful?