Home  >  Q&A  >  body text

Revised title: Calculate total based on checkbox selection

I'm developing a simple financial tracking application. In the application, there is a table with all the expense bills and then the total amount located outside the table.

I'm trying to find a way using JS or AJAX so that when I select 1 checkbox in a table row I can include/exclude a bill from the total and have the total automatically update to reflect the exclusion/include .

The table rows are created dynamically, so every time a new bill is added, the rows will increment, which means the checkbox ID needs to be incremented.

<div class="card-body">
  <table class="display table" style="width:100%" id="example">
    <thead class="table-heading">
      <tr class="table-border">
        <th scope="col">#</th>
        <th scope="col">CREDITOR</th>
        <th scope="col">DESCRIPTION</th>
        <th scope="col">CATEGORY</th>
        <th scope="col">AMOUNT</th>
        <th scope="col" style="text-align: center">INCLUDE / EXCLUDE</th>
      </tr>
    </thead>
    <tbody>
      {% for item in debts %}
      <tr class="table-border table-items">
        <td>{{ forloop.counter }}</td>
        <td>{{ item.creditor }}</td>
        <td>{{ item.description }}</td>
        <td>{{ item.category }}</td>
        <td>£{{ item.amount }}</td>
        <td><input type="checkbox" style="border:2px dotted #00f;display:block;background:#ff0000;" class="table-checkbox" id="myCheckbox" /></td>
      </tr>
      {% endfor %}
    </tbody>
  </table>
</div>

I have a little bit of JS

const checkbox = document.getElementById('myCheckbox')

checkbox.addEventListener('change', (event) => {
  if (event.currentTarget.checked) {
    alert('checked');
  } else {
    alert('not checked');
  }
})

This does trigger the alert when a checkbox is selected, but this will only trigger on the first checkbox since that is the one with the same ID.

So this might be a tricky task as I need the checkbox JS to know what the amount is for the row with the checkbox checked and then subtract that number from the total or vice versa. Maybe this is the wrong approach?

The total number is displayed as:

<h3 class="text-right text-danger"><i class="mdi mdi-cube icon-size float-left"></i><span class="font-weight-bold">£{{total_monthly_outgoing|floatformat:2}}<span class="h6"> per month</span></span></h3>

Thanks

P粉360266095P粉360266095178 days ago3475

reply all(1)I'll reply

  • P粉759457420

    P粉7594574202024-04-05 11:35:00

    You just need to delegate

    I have to expand your span in h3 to avoid JavaScript getting really messy

    Give the total an ID, which is easier than document.querySelector("h3.text-danger span").

    This script does not require an ID

    Contains

    when selected

    const totalContainer = document.querySelector("h3.text-danger span");
    
    document.querySelector(".card-body").addEventListener("click", (e) => {
      if (!e.target.matches(".table-checkbox")) return; // not a checkbox
      const total = [...document.querySelectorAll(".table-checkbox:checked")]
        .map(chk => +chk.closest("td").previousElementSibling.textContent.slice(1)) // remove the pound
        .reduce((a,b)=> a+b); // sum
      totalContainer.textContent = `£${total.toFixed(2)}`;
    })
    .table-checkbox {
      border: 2px dotted #00f;
      display: block;
      background: #ff0000;
    }
    # CREDITOR DESCRIPTION CATEGORY AMOUNT INCLUDE / EXCLUDE
    1 creditor 1 description 1 category 1 £123
    2 creditor 2 description 2 category 2 £223
    3 creditor 3 description 3 category 3 £323

    £0 per month

    reply
    0
  • Cancelreply