Closed adamritter closed 3 weeks ago
Unfortunately the way browsers work for security reasons is all JS has to be attached to the DOM in some way or explicitly evaluated dynamically by existing DOM attached JS code. HTMX uses AJAX style web requests to fetch html data from the server and there is no built in function to execute all JS in the response from these requests. HTMX is just a library for loading html content from the server into a specified target location in the DOM and any script tags of course need to be placed somewhere for them to be allowed to execute.
Appending all required new script tags at the bottom of the page will work but you do risk building up a never ending list of scripts at the bottom of the page with heavy use which could cause problems (htmx history feature for example could save and re-execute all these scripts at once on back button). If the scripts were only required to run once to perform an action and then never run again then you could try making a div with a fixed id that you can replace each time so it only executes once and is then later replaced. You can also place or link to your scripts inline with the content you are updating in your other requests.
If the script code is kind of global and needs to be there all the time then you could instead load this scripts in the head on page load even though they may not be needed initially but when you later add content in later updates it may be able to then link to this already loaded script like for example creating a webcomponent instance based on the already declared webcomponent JS script in the head.
You can also try and use a more browser event driven design where you load custom event listeners at body or specific elements with JS that is loaded in your head page load. Then you can try triggering these custom events from your server responses. Or you can listen on the htmx provided events https://htmx.org/events/ and write custom code to perform the custom actions you require based on the event response data matching your condition.
Thank you very much for the detailed answer, it explains a lot.
What I thought is that it would be nice for some systems if there would be an option for HTMX to just execute the scripts, for example by appending and then removing the script tag anywhere in the DOM (or adding it as a default for none, or some other extension swap style). I looked at the source code though and realized that as my framework depends on the execution order of the oob swaps and scripts being serial, and HTMX swaps all oob swaps one-by-one before handling the rest of the response, so in this case it's much better to use oob swaps for the scripts as well (or use just the web socket extension that I'm using for async swaps right now).
Fixed id and replace works well if I need it, or just making every script tag remove itself after executing something (for example changing just an attribute).
By the way the reason the framework is sending back events inside the response (as opposed to what data-star is doing, sending all responses in a seperate SSE) is that it's much easier to debug the framework response as I see what changes it creates in the DOM in response to the request.
Custom event designs sounds like a great idea, but seem to have the ordering problem.
For now I'll stick with oob tags (and maybe apply your suggestions for removing the script tags).
Thanks, Adam
On Mon, Oct 28, 2024 at 9:29 PM MichaelWest22 @.***> wrote:
Unfortunately the way browsers work for security reasons is all JS has to be attached to the DOM in some way or explicitly evaluated dynamically by existing DOM attached JS code. HTMX uses AJAX style web requests to fetch html data from the server and there is no built in function to execute all JS in the response from these requests. HTMX is just a library for loading html content from the server into a specified target location in the DOM and any script tags of course need to be placed somewhere for them to be allowed to execute.
Appending all required new script tags at the bottom of the page will work but you do risk building up a never ending list of scripts at the bottom of the page with heavy use which could cause problems (htmx history feature for example could save and re-execute all these scripts at once on back button). If the scripts were only required to run once to perform an action and then never run again then you could try making a div with a fixed id that you can replace each time so it only executes once and is then later replaced. You can also place or link to your scripts inline with the content you are updating in your other requests.
If the script code is kind of global and needs to be there all the time then you could instead load this scripts in the head on page load even though they may not be needed initially but when you later add content in later updates it may be able to then link to this already loaded script like for example creating a webcomponent instance based on the already declared webcomponent JS script in the head.
You can also try and use a more browser event driven design where you load custom event listeners at body or specific elements with JS that is loaded in your head page load. Then you can try triggering these custom events from your server responses. Or you can listen on the htmx provided events https://htmx.org/events/ and write custom code to perform the custom actions you require based on the event response data matching your condition.
— Reply to this email directly, view it on GitHub https://github.com/bigskysoftware/htmx/issues/2982#issuecomment-2442558952, or unsubscribe https://github.com/notifications/unsubscribe-auth/AN5SWAF6EU6J6TGAXRKLTGLZ52NA7AVCNFSM6AAAAABQTFNAJOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDINBSGU2TQOJVGI . You are receiving this because you authored the thread.Message ID: @.***>
I'm using HTMX with defaultSwapStyle: none, as I want to send only out-of-band events from my server (just like how it's explained with data-star, even though I prefer using the HTMX library).
I still need to send JS scripts as well, and I believe script tags should still execute even if they don't attach to the DOM in that case.
(as a temporary workaround I'm using a span with hx-swap-oob="beforeend: body" around my script tags)