Triggering events
The server can tell the browser “something happened” by firing a DOM event after the swap: refresh a counter, close a dialog, show a toast. WithTrigger writes the HX-Trigger response header for you, including JSON detail payloads.
using Htmx;
Response.Htmx(h => h.WithTrigger("saved"));Response.Htmx(h => h.WithTrigger("demo-scalar", "plain-value"));Response.Htmx(h => h.WithTrigger("demo-detail", new { id = 42, message = "hello" }));// multiple eventsResponse.Htmx(h => h.WithTrigger("a").WithTrigger("b", new { n = 2 }));Signature: WithTrigger(string eventName, object? detail = null). Detail is serialized with System.Text.Json.
What the server sends
Section titled “What the server sends”| Call | Resulting header |
|---|---|
WithTrigger("saved") |
HX-Trigger: saved |
WithTrigger("demo-scalar", "plain-value") |
HX-Trigger: {"demo-scalar":"plain-value"} |
WithTrigger("demo-detail", new { id = 42, message = "hello" }) |
HX-Trigger: {"demo-detail":{"id":42,"message":"hello"}} |
WithTrigger("a").WithTrigger("b", new { n = 2 }) |
HX-Trigger: {"a":"","b":{"n":2}} (one JSON object; events without detail serialize as "") |
A single event with no detail collapses to the plain name; anything else becomes one JSON object.
What htmx does with it
Section titled “What htmx does with it”htmx 4 documents event names as top-level JSON keys:
- A scalar detail is exposed as
event.detail.value. - An object detail has its properties copied onto
event.detail. - An object may include a
targetkey to dispatch the event on another element.
Listen with hx-on or a normal listener:
<div hx-on:demo-detail="console.log(event.detail.id, event.detail.message)"></div>
<script> document.body.addEventListener("saved", () => alert("Saved!"));</script>A common pattern is to have an element reload itself when an event fires:
<div hx-get="/cart/summary" hx-trigger="item-added from:body"></div>public IActionResult OnPostAdd(int id){ cart.Add(id); Response.Htmx(h => h.WithTrigger("item-added", new { id })); // 204 is not swapped, headers are still processed return NoContent();}Behavior to know
Section titled “Behavior to know”- One header. htmx 4 supports only
HX-Trigger.HX-Trigger-After-SwapandHX-Trigger-After-Settlewere removed. - Merge. If
HX-Triggeris already set (comma-separated names or a JSON object), the existing events are merged in after the ones you set withWithTrigger. - First wins. Calling
WithTriggertwice with the same event name keeps the first detail.
// DemoController.cs — merge casesResponse.Headers["HX-Trigger"] = "demo-pre-a, demo-pre-b";// names + JSON mergedResponse.Htmx(h => h.WithTrigger("demo-added", new { n = 1 }));
Response.Htmx(h => h.WithTrigger("demo-dup", new { v = "first" }).WithTrigger("demo-dup", new { v = "second" }));// -> demo-dup detail is { v: "first" }See the live demo: run dotnet run --project samples/Htmx4.Sample and open /Triggers (source).
Related: Response headers, htmx 4 reference: HX-Trigger, migration guide.
From the blog: Update HTML Elements with Htmx Triggers and ASP.NET Core.