lukphin
lukphin

Reputation: 13

Why htmx trigger only work once in django

I am using htmx to trigger a field in Django ModelForm with the following codes. Everything works as it supposed to the first time around, but after that when you change the option select field nothing happen, no trigger whatsoever. I have to reset and go back to url 'listing' for it to respond again. I want the code to trigger the result everytime I change the option select field before I finally submit. Any help is well appreciated.

class Listing(model.Model):
   option=models.ForeignKey(Option,on_delete=models.CASCADE)
   package=models.ForeignKey(Package,on_delete=models.CASCADE,blank=True,null=True)
   number=models.ForeignKey(Number,on_delete=models.CASCADE,blank=True,null=True)
   period=models.ForeignKey(Period,on_delete=models.CASCADE,blank=True,null=True)
   title=models.CharField(max_length=20)


class ListingForm(ModelForm):
   class Meta:
      model=Listing
      fields='__all__'

class ListingCreateView(CreateView):
   model=Listing
   form_class=ListingForm
   template_name='listing_form.html'
   success_url='/forms/listing/'

def option(request):
   option=request.GET.get('option')
   form=ListingForm
   context={'option':option,'form':form}
   return render(request,'partial_option.html',context)

urlpatterns=[
   path('',ListingCreateView.as_view(),name='listing-create'),
   path('option/',option,name='option'),
]

listing_form.html
{% load widget_tweaks %}
<!DOCTYPE html>
<html>
    <head>
         <script src="https://unpkg.com/[email protected]"></script>
    </head>
    <body>
        <h1>Listing Form</h1>
        <form method="post">
            {% csrf_token %}
            <div>
                {{ form.option.label_tag }}
                {% render_field form.option hx-get="/forms/option" 
                hx-trigger="change" hx-target="#option" hx-swap="outerHTML" %}
            </div>
            <div id="option"></div>
            <input type="submit" value="Send">
         </form>
         <script>
             document.body.addEventListener('htmx:configRequest', (event) =>
             {
                 event.detail.headers['X-CSRFToken']='{{csrf_token}}';
             })
         </script>
     </body>
 </html>

 partial_option.html:
 {% if option %}
    {% if option =='1' %}
        <p>You have chosen option 1</p>
    {% elif option == '2' %}
        <p>You have chosen option 2</p>
        {{ form.package.label_tag }}
        {{ form.package }}
    {% elif option == '3' %}
        <p>You have chosen option 3</p>
        {{ form.number.label_tag }}
        {{ form.number }}
        {{form.period.label_tag }}
        {{ form.period }}
    {% endif %}
 {% else %}
    <p>You have no option</p>
 {% endif %}
 {{ form.title.label_tag }}
 {{ form.title }}

Upvotes: 1

Views: 2245

Answers (1)

Dauros
Dauros

Reputation: 10502

You have set the hx-swap="outerHTML" method, so HTMX will replace the target element with the response. Since your response does not contain a new <div id="option"> element, after the first request/swap cycle HTMX cannot find the target.

To solve this issue, change the swap method to innerHTML or embed the response in a <div id="option"></div> element.

Upvotes: 3

Related Questions