Skip to content

Commit 5a67907

Browse files
move hx-trigger response header timing to after swap (#3900)
1 parent d3d4dea commit 5a67907

4 files changed

Lines changed: 23 additions & 24 deletions

File tree

src/htmx.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,9 @@ var htmx = (() => {
644644
this.__trigger(elt, "htmx:error", {ctx, error})
645645
} finally {
646646
clearTimeout(ctx.requestTimeout);
647+
if (ctx.hx?.trigger) { // HX-Trigger
648+
this.__handleTriggerHeader(ctx.hx.trigger, ctx.sourceElement);
649+
}
647650
this.__trigger(elt, "htmx:finally:request", {ctx})
648651
if (!ctx.keepIndicators) {
649652
this.__hideIndicators(indicators);
@@ -672,9 +675,6 @@ var htmx = (() => {
672675
// Handle response headers that abort normal swap processing.
673676
// Returns true if the response was fully handled by a header.
674677
__handleHeadersAndMaybeReturnEarly(ctx) {
675-
if (ctx.hx.trigger) { // HX-Trigger
676-
this.__handleTriggerHeader(ctx.hx.trigger, ctx.sourceElement);
677-
}
678678
if (ctx.hx.refresh === 'true') { // HX-Refresh
679679
location.reload();
680680
return true

test/tests/unit/__handleHxHeadersAndMaybeReturnEarly.js

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,6 @@ describe('__handleHxHeadersAndMaybeReturnEarly unit tests', function() {
88
cleanupTest();
99
});
1010

11-
it('handles hx-trigger header', function () {
12-
let triggerFired = false
13-
let listener = () => { triggerFired = true }
14-
15-
let container = createProcessedHTML('<div></div>')
16-
container.addEventListener('myEvent', listener)
17-
18-
let ctx = {
19-
hx: {
20-
trigger: 'myEvent'
21-
},
22-
sourceElement: container
23-
}
24-
25-
let result = htmx.__handleHeadersAndMaybeReturnEarly(ctx)
26-
27-
assert.isNotOk(result)
28-
assert.isTrue(triggerFired)
29-
})
30-
3111
it('returns false when no headers to handle', function () {
3212
let ctx = {
3313
hx: {},

test/tests/unit/__issueRequest.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,23 @@ describe('__issueRequest unit tests', function() {
177177
assert.equal(capturedError, testError)
178178
})
179179

180+
it('fires HX-Trigger event after swap completes', async function () {
181+
let div = createProcessedHTML('<div hx-get="/test" hx-swap="none"></div>')
182+
let ctx = htmx.__createRequestContext(div, new Event('click'))
183+
184+
let triggerFired = false
185+
div.addEventListener('myEvent', () => triggerFired = true)
186+
187+
ctx.fetch = async () => ({
188+
status: 200,
189+
headers: new Headers({ 'HX-Trigger': 'myEvent' }),
190+
text: async () => ''
191+
})
192+
193+
await htmx.__issueRequest(ctx)
194+
assert.isTrue(triggerFired)
195+
})
196+
180197
it('always triggers htmx:finally:request', async function () {
181198
let div = createProcessedHTML('<div hx-get="/test" hx-swap="none"></div>')
182199
let ctx = htmx.__createRequestContext(div, new Event('click'))

www/src/content/reference/02-headers/10-HX-Trigger.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ title: "HX-Trigger"
33
description: "Triggers client-side events with `htmx.trigger()`"
44
---
55

6-
The `HX-Trigger` response header triggers client-side events when a response is received.
6+
The `HX-Trigger` response header triggers client-side events after the swap has completed.
77

88
## Basic Usage
99

@@ -104,6 +104,8 @@ _This example uses the [`hx-live`](/extensions/hx-live) extension._
104104

105105
Response headers are not processed on 3xx response codes. Return a 2xx status when using this header.
106106

107+
In htmx 2, there were three variants: `HX-Trigger`, `HX-Trigger-After-Swap`, and `HX-Trigger-After-Settle`. In htmx 4, these were consolidated into a single `HX-Trigger` header that fires after the swap completes.
108+
107109
## See Also
108110

109111
- [`htmx.trigger()`](/reference/methods/htmx-trigger)

0 commit comments

Comments
 (0)