Search code examples
pythondjangohtmx

htmx: hx-target-error fails when hx-target defined (django python)


I am using the htmx extension "response-targets" via "hx-ext" in a python django project.

The Problem

"hx-target-error" will not work when "hx-target" is also defined, but works when it is the only target.

Environment

htmx 1.9.10, response-targets 1.9.10, python 3.12, django 5.0.1

Example html:

<div hx-ext="response-targets">
    <button
        hx-get={% ur "appname:endpoint" %}
        hx-target-error="#id-fail"
        hx-target="#id-success"
        type="submit"
     >
         Press Me!
     </button>
</div>

hx-target

I have tried with various other types of targets such as "next td", "next span", etc. All of them produce a valid target value "request.htmx.target" in the endpoint defined in views.py.

hx-target-error

I have also tried various alternatives supported in response-targets such as "hx-target-*", "hx-target-404", etc with no change in results.

I verified that "response-targets" is installed correctly and being used correctly because when "hx-target" is removed from the "button", then "hx-target-error" works.

Error generation in views.ph

@login_required
def endpoint(request)
    return HttpResponseNotFound("Not found 404")

Logs

Bad Request: /testbed/endpoint/
127.0.0.1 - [27/Feb/2024] "GET /testbed/endpoint/ HTTP/1.1" 404

response-targets extension

https://htmx.org/extensions/response-targets/


Solution

  • Resolved: The solution is to move the "hx-ext" attribute <div hx-ext="response-targets"> to a higher encompassing level than any DOM elements referenced by either "hx-target" or "hx-target-error".

    In my case, "hx-target-error" pointed to a div 'id' outside of the div containing "hx-ext".

    Thank you @guigui42 for suggesting this solution

    Example incorrect usage:

    <tr>
        <td>
            <div hx-ext="response-targets">
                <button
                    hx-get={% url "testbed:rebound" %}
                    hx-headers='{"custom": "{{ test.id }}"}'
                    hx-target-error="#GET-{{ test.id }}-fail"
                    hx-target="#GET-{{ test.id }}-ok"
                    class="btn btn-sm btn-primary testbed-btn"
                >
                    GET {{ test.msg }}
                </button>
            </div>
        </td>
        <td>
            <span id="GET-{{ test.id }}-ok" />
            <span class="text-danger" id="GET-{{ test.id }}-fail" />
        </td>
    </tr>
    

    Example correct usage:

    <tr hx-ext="response-targets">
        <td>
            <button
                hx-get={% url "testbed:rebound" %}
                hx-headers='{"custom": "{{ test.id }}"}'
                hx-target-error="#GET-{{ test.id }}-fail"
                hx-target="#GET-{{ test.id }}-ok"
                class="btn btn-sm btn-primary testbed-btn"
            >
                GET {{ test.msg }}
            </button>
        </td>
        <td>
            <span id="GET-{{ test.id }}-ok" />
            <span class="text-danger" id="GET-{{ test.id }}-fail" />
        </td>
    </tr>