0

I am using HTMX with Django to submit a contact form without refreshing the page. When the form has errors, my backend correctly returns the contact_messages.html template, but the errors do not appear in the page after the request.

I can see the correct response in the Network tab, and contact_messages.html contains the expected validation messages. However, HTMX does not update the div#contact-messages in my contact.html file.

Before trying to use HTMX, Django's built-in form validations work perfectly. However, as everyone knows, the process is synchronous, and I want to make it asynchronous with HTMX.

This's mi view:

class ContactView(FormView):

    template_name = 'contact/contact.html'
    form_class = ContactForm
    success_url = reverse_lazy('contact')

    def form_valid(self, form):        

        messages.success(self.request, "Your message has been sent. We will be in touch with you as soon as possible.")
        return redirect(self.success_url + '#contact-section')


    def form_invalid(self, form):
        messages.error(
            self.request,
            "There were some errors in your submission. Please review the highlighted fields and try again",
            extra_tags="danger")

        if self.request.headers.get("HX-Request"):
            return render(self.request, "contact/contact_messages.html", {"form": form}, content_type="text/html", status=400)

        return super().form_invalid(form)

This's my form in contact.html:

<form id="contact-form" method="post" hx-post="{% url 'contact' %}"
                         hx-target="#contact-messages"  hx-swap="innerHTML" novalidate>

                        {% csrf_token %}

                        <div id='contact-messages'>
                            {% include 'contact/contact_messages.html' %}

                        </div>


                        <div class="form-group mb-0">
                            <button class=" btn btn-primary w-100">
                                <span>Send Message</span>
                            </button>
                        </div>

                       
                    </form>

This's my secondary template contact_messages.html:

% if messages %}
    {% for message in messages %}
        <div class="alert alert-{{ message.tags }}" role="alert">
            {{ message }}
            <button type="button" class="close" data-dismiss="alert" aria-label="Close">
                <span aria-hidden="true">&times;</span></button>
        </div>
    {% endfor %}
{% endif %}

{% for field in form %}
    <div class="form-group">
        {{ field }}
        {% if form.errors %}
            <div class="invalid-feedback d-block">
                {% for error in field.errors %}
                    {{ error }}
                {% endfor %}
            </div>
        {% endif %}
    </div>
{% endfor %}

Here you can see that Django returns the correct response, but I can't get it to be reflected in contact.html.

enter image description here

2
  • Any errors in the web console? Seems like there's a few Commented Feb 7 at 15:30
  • This's the main errors en in the web console: "Here are the errors from the browser console:" POST 127.0.0.1:8004/contact 400 (Bad Request) The form submission fails with a 400 Bad Request response. The response contains validation errors, but HTMX does not update the page. Commented Feb 7 at 15:47

1 Answer 1

2

By design HTMX does not swap content when error response is returned (4xx).

Here's one way to get around this:

HTMX - Allow HTTP error 400 and 422 swap content to enable showing validation errors

Another way is to simply return 200 instead of 400.

Sign up to request clarification or add additional context in comments.

1 Comment

my friend, thanks so much for your help, that was the problem, I fixed it by removing the status property in render method.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.