Search code examples
djangopayloadhtmx

Trying to send multiple values in a htmx request [Django] [HTMX]


I'm encountering an issue when trying to send two values from the frontend to the backend using htmx. Here's my code:

{% include "base.html" %}

{% block content %}
<div class='flex flex-col h-screen w-screen overflow-y-hidden'>
    {% include "sidebar.html" %}
    <div class='h-full flex items-center justify-center'>
        <div class='w-4/5 max-h-screen h-4/5 border border-black flex flex-col overflow-x-hidden overflow-y-scroll mb-12'>
            <!-- Form Data -->
            {% for field, value in data.items %}
                <div class='w-full h-28 p-1 m-5 flex flex-col mx-24'>
                    <label for="{{ field }}" class="block mb-2 text-sm font-medium text-gray-900">{{ field }}</label>
                    <input type="hidden" name="field" value="{{ field }}">
                    <input type="text" name="value" value="{{ value }}" 
                        class="editable-field bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-3/4 p-2.5" 
                        hx-trigger="blur" hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}' 
                        hx-post="{% url 'form' formId %}" 
                        hx-vals='{"field": "{{ field }}", "value": "{{ value }}"}'>
                </div>
            {% endfor %}
            <!-- End form data  -->
        </div>
    </div>
</div>

{% endblock content %}

I've tried using hx-vals and included quotes for those values, but the backend only receives the value, not the field. Here's the output in the backend:

<QueryDict: {'value': ['valiue']}>
valiue None

In my view, I'm attempting to retrieve both values using the following code:

def post(self, request, formId):
       print(request.POST)
       field = request.POST.get('field')
       value = request.POST.get('value')
       print(value, field)

I've tried using hx-vals, and changing the value of the input to the field property (removing it), and that works, but it's not a feasible solution for my scenario. I noticed that in the payload, the field is not present, leading me to believe that only the value of the input is being sent, and the hx-vals property is being ignored.

Is there a way to send both the field and value using htmx, or do I need to explore alternative approaches? Any guidance would be appreciated


Solution

  • Solved, Use the hx-focusout and add a form tag, I avoided the form tag as I had a misconception that it required a button with the type of submit, here's the code which is working

    {% include "base.html" %}
    
    {% block content %}
    <div class='flex flex-col h-screen w-screen overflow-y-hidden'>
        {% include "sidebar.html" %}
        <div class='h-full flex items-center justify-center'>
            <div class='w-4/5 max-h-screen h-4/5 border border-black flex flex-col overflow-x-hidden overflow-y-scroll mb-12'>
                <!--Form Data-->
                {% for field, value in data.items %}
                    <div class='w-full h-28 p-1 m-5 flex flex-col mx-24'>
                        <form  hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}' hx-trigger="focusout" hx-post="{% url 'form' formId %}">
                            <label for="{{ field }}" class="block mb-2 text-sm font-medium text-gray-900">{{ field }}</label>
                            <input type="hidden" name="field" value="{{ field }}">
                            <input type="text" name="value" value="{{ value }}" 
                            class="editable-field bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-3/4 p-2.5"  >
                        </form>
                    </div>
                {% endfor %}
                <!--End form data -->
            </div>
        </div>
    </div>
    
    {% endblock content %}
    

    the hx-blur only sends the value inside the input and not on the form, but triggering the form using focusout sends the data in both inputs to the backend