Computing totals in formsets when only part of the data is rendered

Good day!

I’m building a budgeting feature where I use a Django modelformset to render a list of items with their prices and quantities. The totals are calculated client-side using JavaScript. Here’s a simplified version of what each row looks like:

<tr class="table-row orcamento-row">
  <td>{{ form.instance.item_name }}</td>
  <td>R$ <span class="item-price">{{ form.instance.item_price }}</span></td>
  <td>
    <button onclick="decreaseValue(this)">-</button>
    {{ form.quantity }}
    <button onclick="increaseValue(this)">+</button>
  </td>
  <td>R$ <span class="total-price">{{ form.instance.total_price }}</span></td>
</tr>

I also have a JavaScript function that sums up all the total-price spans to compute the total amount committed (“total empenhado”):

function compute_total_empenhado() {
    let total = 0;
    document.querySelectorAll("tr.orcamento-row span.total-price").forEach(td => {
        total += parseFloat(td.textContent.replace(',', '.')) || 0;
    });
    // update DOM
}

This works well until I use the search functionality.

When I search the table (e.g., by item name), the backend returns a partial template that only includes the matching rows (the formset via context).

As a result, the total computed in JS is no longer accurate, because it only includes visible rows (not the full formset data).

Below one example before search and after.

How should I handle this?

Fundamentally, you have two basic options.

1 - Have the server return all results, and change the JavaScript in the browser to only show the elements being searched for. (Hide all the other elements.)

2 - Perform the calculation on the server, and return the total with the list of elements.

(There are some variations possible with this, but these are the two basic ideas.)

1 Like

Thanks for the tip!

I ended up going with the second option — calculating the total on the server and returning it along with the filtered list.

It also helped me realize that I was overcomplicating things by recalculating the entire total_empenhado every time the item quantity changed. By keeping track of the previous quantity, I was able to compute just the delta and update the total incrementally.

Appreciate your support!