Search code examples
djangoalpine.jshtmx

HTMX not working when loaded within template tag using Alpine js (x-if)


For a Django project I am trying to build a toggle component to switch from list to grid view without reloading the page. I am using a Flowbite toggle component. Using Alpine's x-if I am able to dynamically change the HTML for the list view and the grid view which are contained in two template tags within the same alpine component. Here is a simplified version of the component:

<div x-data="{ value: false }">

  <!-- Toggle component from Flowbite -->
  <label class="relative inline-flex items-center cursor-pointer">
    <input x-model="value" type="checkbox" value="" class="sr-only peer">
    <div class="w-11 h-6 bg-slate-300 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-yellow-300 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-yellow-500"></div>
    <span class="ml-2 font-medium text-slate-600 mdi mdi-view-grid"></span>
  </label>

  <!-- Template tags with the HTML code -->
  <template x-if="value===true">
    <div>
      <a href="{% url 'inventory:inventory' %}">HREF</a>
    </div>
  </template>

  <template x-if="value===false">
    <div>
      <a hx-get="{% url 'inventory:inventory %}">HX-GET</a>
    </div>
  </template>

</div>

The toggle works just fine. However, while the toggled code with the href url works just fine, the code with the hx-get attribute (HTMX) does not work. Clicking on the link does not do anything. I suppose this has to do with inserting HTMX properties after the page is already loaded, thus HTMX does not 'see' the code toggled via alpine js.

I tried to apply hx-on (with htmx:load to the main div but I could not make it work. What can be done to make the hx-get attribute work after being added to the page via alpine?


Solution

  • HTMX mentions this phenomena in the documentation, you have to call htmx.process() on the DOM elements that were not present/visible on page load. You can call this method from e.g. a $watch:

    <div id="mycomponent" 
         x-data="{ value: false }" 
         x-init="$watch('value', new_value => {htmx.process(htmx.find('#mycomponent'))})">