How to change hx-get value dynamically? – Django

by
Ali Hasan
alpine.js django htmx

Quick Fix: Call htmx.process() after the button attributes are changed to force htmx to reparse the updated DOM.

The Problem:

You have a button in a template that opens a dialog located in another template. You want to dynamically change the hx-get attribute of the button based on a user action in that template. The button is initially set to make a GET request to a specific URL, but you want to be able to update the URL based on user input. However, when you try to update the hx-get attribute in JavaScript, it’s not being applied correctly, and the button still makes the request to the initial URL specified in the template.

The Solutions:

Solution 1: Force Htmx to Reparse DOM

The issue arises because of missing to call `htmx.process()` after updating the button’s attributes. Using `htmx.process()` forces Htmx to reparse the updated DOM, enabling it to recognize the changes made to the `hx-get` attribute. Here’s the updated code:

In another_template.html:

<script>
  document.addEventListener('alpine:init', () => {
    Alpine.data('dialog', () => ({
      handleButtonClick(id) {
        console.log(id); // prints the expected id correctly
        const button = document.getElementById('btn_id');
        const url = `/some_url/${id}`;
        button.setAttribute('hx-get', url);
        console.log(button.attributes); // prints the updated `hx-get` with the id included
        htmx.process(button); // <-- Added `htmx.process()` to force Htmx to reparse the updated DOM.
        button.click();
      },
    }));
  });
</script>

By incorporating htmx.process(), you ensure that Htmx acknowledges the modifications made to the hx-get attribute, allowing the button to load the correct data dynamically. This resolves the problem where the hx-get value was not being updated dynamically.

Solution 2: Use htmx:configRequest and htmx:afterRequest events

Once a node has been processed by htmx, the hx-get attribute is stored internally and changing it in the element won’t make a difference.

One way to change it is by using the htmx:configRequest event. You can add a listener to the window and have it check for the presence of a data-htmx-url attribute and use that if present, otherwise leave the path untouched. Then in your current code set a data-htmx-url attribute on the button with the new URL.

window.addEventListener('htmx:configRequest', (event) => {
  if (event.srcElement.getAttribute('data-htmx-url')) {
    event.detail.path = event.srcElement.getAttribute('data-htmx-url');
  }
});

Finally, you could combine this with the htmx:afterRequest to remove the attribute when the request is done.

window.addEventListener('htmx:afterRequest', (event) => {
  event.detail.elt.removeAttribute('data-htmx-url');
});

Q&A

Which function is used to force htmx to reparse the updated DOM?

htmx.process()

What needs to be done after updating hx-get attribute?

htmx.process() to force htmx to reparse the updated DOM

Video Explanation:

The following video, titled "Django Dynamic Forms Tutorial with Htmx - YouTube", provides additional insights and in-depth exploration related to the topics discussed in this post.

Play video

... Read the blog post https ... HTMX - hx-boost Attribute for Progressively Enhancing Web-Apps.