javascripthtmx

Using htmx HX-Trigger with JSON in body of response


I want my htmx response to trigger an event using the HX-Trigger, but the 'details' of the event are too large to put in the response header. Is there a way to access the JSON content of the response in the event handler?

For example, given this (Python, FastHTML) server-side code producing a response that just triggers an event name:

return Response(
    headers={"HX-Trigger": "replaceGraph"},
    media_type="application/json",
    content=json.dumps(content),
)

…or a slightly more complicated example that triggers the event on another element:

return Response(
    headers={"HX-Trigger": json.dumps({"replaceGraph": {"target": "#target-id"}})},
    media_type="application/json",
    content=json.dumps(content),
)

I want this client-side code:

document.body.addEventListener('replaceGraph', evt => {
   // Get access to JSON content of the response.
});

Solution

  • Here's a working solution, albeit not terribly elegant.

    document.addEventListener('DOMContentLoaded', () => {
    
        // Capture and store the response from HTMX before it is used to update the DOM.
        document.body.addEventListener('htmx:beforeOnLoad', evt => {
            const response = evt.detail.xhr.response;
            const contentType = evt.detail.xhr.getResponseHeader('Content-Type') || '';
            const wasJSON = contentType.includes('application/json');
            window._last_htmx_response = wasJSON ? JSON.parse(response) : response;
        });
    
        document.body.addEventListener('replaceGraph', evt => {
            const data = window._last_htmx_response;
            console.log(`The JSON for this response was: ${data}`);
        });
    });
    

    The beforeOnLoad event is triggered before any processing occurs, so we can store the result. Yes, this generic approach might perform JSON parsing on results that don't need it. You can alternatively defer the JSON parsing into event handlers where you know it will be used, or perhaps only when the HX-Trigger header is present.

    If someone has a better solution, I'll happily switch the accept mark to there.