I have a simple finance tracker app that I am working on. Within the app, there is a table of all outgoing bills and then a total figure that sits outside of the table.
I'm trying to find a way to use JS or AJAX so that when I select a checkbox within 1 of the table rows I can include/exclude the bill from the total and have the total automatically update to reflect the exclusion/inclusion.
The table rows are dynamically created so each time a new bill is added the rows increase which means the checkbox ID would need to increase.
<div >
<table style="width:100%" id="example">
<thead >
<tr >
<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 >
<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;" id="myCheckbox" /></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
I've got this bit of JS
const checkbox = document.getElementById('myCheckbox')
checkbox.addEventListener('change', (event) => {
if (event.currentTarget.checked) {
alert('checked');
} else {
alert('not checked');
}
})
That does fire the alert when the checkbox is checked, but this only fires on the first checkbox as this is the checkbox with the same ID.
So this is probably a tricky task to solve, as I would need the checkbox JS to know what the amount is for the row the checkbox is checked for and then subtract that figure from the total or vice/versa. Maybe this is the wrong approach?
The total is displayed as:
<h3 ><i ></i><span >£{{total_monthly_outgoing|floatformat:2}}<span > per month</span></span></h3>
Thanks
CodePudding user response:
You just need to delegate
I had to unwrap your span in the h3 to not make very messy JavaScript
Give the total an ID to make it easier than document.querySelector("h3.text-danger span")
.
You do not need IDs for this script
INCLUDE when checked
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;
}
<div >
<table style="width:100%" id="example">
<thead >
<tr >
<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>
<tr >
<td>1</td>
<td>creditor 1</td>
<td>description 1</td>
<td>category 1</td>
<td>£123</td>
<td><input type="checkbox" /></td>
</tr>
<tr >
<td>2</td>
<td>creditor 2</td>
<td>description 2</td>
<td>category 2</td>
<td>£223</td>
<td><input type="checkbox" /></td>
</tr>
<tr >
<td>3</td>
<td>creditor 3</td>
<td>description 3</td>
<td>category 3</td>
<td>£323</td>
<td><input type="checkbox" /></td>
</tr>
</tbody>
</table>
<h3 ><i ></i><span >£0</span><span > per month</span>
</h3>
</div>
EXCLUDE when checked
const totalContainer = document.querySelector("h3.text-danger span");
let total = [...document.querySelectorAll(".table-checkbox")]
.map(chk => chk.closest("td").previousElementSibling.textContent.slice(1)) // remove the pound
.reduce((a,b)=> a b); // sum
document.querySelector(".card-body").addEventListener("click", (e) => {
const tgt = e.target;
if (!tgt.matches(".table-checkbox")) return; // not a checkbox
const val = tgt.closest("td").previousElementSibling.textContent.slice(1);
total = val*(tgt.checked ? -1 : 1)
totalContainer.textContent = `£${total.toFixed(2)}`;
})
.table-checkbox {
border: 2px dotted #00f;
display: block;
background: #ff0000;
}
<div >
<table style="width:100%" id="example">
<thead >
<tr >
<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>
<tr >
<td>1</td>
<td>creditor 1</td>
<td>description 1</td>
<td>category 1</td>
<td>£123</td>
<td><input type="checkbox" /></td>
</tr>
<tr >
<td>2</td>
<td>creditor 2</td>
<td>description 2</td>
<td>category 2</td>
<td>£223</td>
<td><input type="checkbox" /></td>
</tr>
<tr >
<td>3</td>
<td>creditor 3</td>
<td>description 3</td>
<td>category 3</td>
<td>£323</td>
<td><input type="checkbox" /></td>
</tr>
</tbody>
</table>
<h3 ><i ></i><span >£669.00</span><span > per month</span>
</h3>
</div>