Htmx и django: отображение обратной связи при успешном/неуспешном запросе

Я пытаюсь отобразить сообщение обратной связи, говорящее "добавлено" или "не удалось", когда форма отправляется с помощью HTMX на мой бэкенд Django.

По сути то, что я имею сейчас - это форма, которая выполняет hx-post, а ответ - это div, содержащий обновленную информацию, которая меняется местами с текущим содержимым div.

<div id="list">
    <!-- The stuff in here is loaded through another template, which is
         the result of a successful myApp:add operation. -->
</div>
<form hx-post="{% url 'myApp:add' eid=e.id %}" hx-swap="outerHTML" hx-target="#list">
    <!-- Some stuff in here -->
</form>
<div id="result">
    <!-- Here I should print a message saying correct or incorrect
         depending on the HTMX result (if the entry was added or there was
         any kind of error, even connection errors) -->
</div>

Дело в том, что в случае ошибки в форме или в самом запросе, список останется прежним, но я хотел бы, чтобы он вывел что-то вроде "error" в div result. Если же новая запись будет добавлена правильно, я хотел бы вывести сообщение "success" в div результата.

Обратите внимание, что я не могу вернуть result div как часть DOM ответа hx-post, поскольку соединение может не установиться. Поэтому сообщение о неудаче не будет отображено.

Я также использую Alpine.js, если это может помочь.

Вот один из способов сделать это с помощью Alpine, если вы можете добавить div вокруг существующего кода:

<div x-data="{ state: '' }" 
    @htmx:send-error="state = 'send error'" 
    @htmx:response-error="state = 'response error'" 
    @htmx:after-swap="state = 'success'"
>
    <div id="list"></div>

    <form hx-post="{% url 'myApp:add' eid=e.id %}" hx-swap="outerHTML" hx-target="#list">
        <button type="submit">Submit</button>
    </form>

    <div id="result">
        <span x-text="state"><
    </div>
</div>

События срабатывают на целевой части #list, поэтому они распространяются на родительский div. Если вы предпочитаете добавить компонент Alpine в div #result, вы можете сделать это, прослушивая события в окне:

<div id="result" x-data="{ state: '' }" 
    @htmx:send-error.window="state = 'send error'" 
    @htmx:response-error.window="state = 'response error'" 
    @htmx:after-swap.window="state = 'success'">
    <span x-text="state"></span>
</div>

Если вы используете второй подход и у вас несколько htmx-запросов на одной странице, вы также можете прочитать значение $event.detail.target.id в событиях Alpine, чтобы добавить некоторую логику. В приведенном выше случае значение должно быть list.

Вернуться на верх