Search code examples
djangoswaphtmx

hx-swap-oob creates duplicate dom element?


I have this workflow:

  1. new record is being inserted in database
  2. using HTMX, the row inserted should show up in table (the whole table gets reRendered)
  3. simuoultaneously with previous step, certain number should show up in a paragraph element (paragraph gets reRendered).

I've tried to accomplish this using hx-swap-oob="true" argument on a paragraph element but the problem is that DOM element (paragraph) is being duplicated for some reason. Can someone tell me why is this happening and how to solve this?

Template.html

<table class="ui celled table">
    <thead>
        <tr>
            <th>Col 1</th>
            <th>Col 2</th>
            <th>Col 3</th>
        </tr>
    </thead>
    <tbody hx-post="{% url 'books' book.id %}" hx-trigger="addBook from:body" hx-vals='{"action": "show_editions"}' id="book_list">
        {% include "selling-books.html" %}
    </tbody>
</table>
...
... # some other DOM elements
...
<p id="book_number">{{ book.number }}</p>

Selling-books.html

{% for edition in editions %}
<tr>
    <td>{{ edition.in }} pieces</td>
    <td>{{ edition.out }} pieces</td>
    <td>{{ edition.price }} USD</td>
</tr>
{% endfor %}

<p hx-swap-oob="true" id="book_number">{{ book.number }}</p>

Views.py

def book_status(request, template_name = 'book.html', id=""):
    book = Book.objects.get(id=id)
    editions = Edition.objects.filter(book_id=id)

    if request.method == "POST":
            action = request.POST.get('action')
            
            if action == 'addBook':
                addEdition_form = AddBookForm(request.POST or None)
                if addEdition_form.is_valid():
                    ... some logic ...
                    
                    return HttpResponse(status=204, headers={'HX-Trigger': 'addBook'})

            if action == 'show_editions':
                for edition in editions:
                    ... some logic ...
                return render(request, 'selling-book.html', {'editions': editions, 'book': book})
    
    else:
        return render(request, template_name, {'book':book, 'editions':editions, 'addEdition_form': addEdition_form})   

Solution

  • You can avoid the duplicate by checking if the addEdition_form variable exists in your template.

    Altervative solution may be to split the table content and counter paragraph into seperate templates.