Skip to content

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.

event.detail.value
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 events
Response.Htmx(h => h.WithTrigger("a").WithTrigger("b", new { n = 2 }));

Signature: WithTrigger(string eventName, object? detail = null). Detail is serialized with System.Text.Json.

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.

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 target key 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();
}
  • One header. htmx 4 supports only HX-Trigger. HX-Trigger-After-Swap and HX-Trigger-After-Settle were removed.
  • Merge. If HX-Trigger is already set (comma-separated names or a JSON object), the existing events are merged in after the ones you set with WithTrigger.
  • First wins. Calling WithTrigger twice with the same event name keeps the first detail.
// DemoController.cs — merge cases
Response.Headers["HX-Trigger"] = "demo-pre-a, demo-pre-b";
// names + JSON merged
Response.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.