I'm currently building a website with django and htmx and i like the combination so far. Let's say I use an htmx attribute on a button to replace a div in the DOM with another div that is supposed to contain a wysiwyg editor. Now the wysiwyg editor has to be initialized with JavaScript. How do I do this? Can I just return the script tag under the editor div that is being requested with htmx? Wouldn't that be also a little ugly or bad practice because you'd have script tags in the middle of the html body? What's the best way of solving this?
Short Answer
To run specific code after an HTMX request, you need to be listening for the htmx:afterRequest event.
Whether it's just a single htmx:afterRequest event that you are trying to listen to (or if you have code that should run after all htmx requests), you can use the below event listener to run your code after any HTMX request is completed:
document.addEventListener('htmx:afterRequest', function(evt) {
// Put the JS code that you want to execute here
});
Long Answer
If you want it to run after a specific event only, you need access to the evt object associated with the event, to which you should refer to the official docs here in full. However I have put some simple examples below to demonstrate what this can look like.
document.addEventListener('htmx:afterRequest', function(evt) {
if(evt.detail.xhr.status == 404){
/* Notify the user of a 404 Not Found response */
return alert("Error: Could Not Find Resource");
}
if (evt.detail.successful != true) {
/* Notify of an unexpected error, & print error to console */
alert("Unexpected Error");
return console.error(evt);
}
if (evt.detail.target.id == 'info-div') {
/* Execute code on the target of the HTMX request, which will
be either the hx-target attribute if set, or the triggering
element itself if not set. */
let infoDiv = document.getElementById('info-div');
infoDiv.style.backgroundColor = '#000000'; // black background
infoDiv.style.color = '#FFFFFF'; // white text
}
});
For a full list of HTMX events you can listen to (e.g. htmx:configRequest to modify the HTMX AJAX request before it is sent) check out the official reference here.
As to the question of where to put this in your code, the only technical necessity is to be listening for the event before the event triggers: i.e. do not send this code in your response, already have it in your page beforehand. Then where to put stylistically is essentially a matter of preference. In a Django + HTMX stack, it would be perfectly valid to either include this as a script tag within the template itself, or put it inside a static js file and link to it. Just make sure the HTMX library is loaded before this executes, and you have accounted for csrf issues appropriately.
Edit: As has been well pointed out by @Leon_G84, you can achieve much of the above without listening to events in your .js files, and instead listen to them via the hx-on::after-request attribute inside your HTML elements. You still need to define any custom subroutines in your .js files or <script> tags, and ensure they're within scope appropriately.
Example:
<script>
function performAnimation(evt) {
// Insert animation based code
}
</script>
<div id="text-box"></div>
<button
hx-get="/text"
hx-target="#text-box"
hx-on::after-request="performAnimation()">
Press Me
</button>
Note 1: it is after-request, not afterRequest, when accessed through the HTML element's hx-on attribute. This is because DOM attributes are treated as case insensitive.
Note 2: One can apply the above logic to other HTMX DOM events, like beforeRequest and afterSettle etc. Check the docs to work out exactly what event(s) you should be responding to for your specific use case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With