-1

I'm having a trouble on how can I count total check in table checkbox and total all amount on amount column based of what been checked in checkbox field.I'm new in javascript and html. It would be great if anyone can help me with this problem, thanks in advance!

function toggle(source) {
  checkboxes = document.getElementsByName('product_id[]');
  for(var i=0, n=checkboxes.length;i<n;i++) {
  checkboxes[i].checked = source.checked;
 }
 }
<table class="table" name="table" id="table">
        <thead>
          <tr >
          <th></th>
          <th ><input type="checkbox" onClick="toggle(this)" /></th>
          <th>Name</th>
          <th>Amount</th>
          <th>Another value</th>
          </tr>
        </thead>
        <tbody >
          <tr>
            <td></td>
            <td><input type="checkbox" name="product_id[]"></td>
            <td>Jessica</td>
            <td>5200</td>
            <td>somethingnew</td>
          </tr>

          <tr>
            <td></td>
            <td><input type="checkbox" name="product_id[]" ></td>
            <td>Jessica</td>
            <td>800</td>
            <td>Somevalue</td>
          </tr>            
        </tbody>
    </table>
          Number of checkbox = <p id="total_checked"></p>
          Totol amount = <p id="total_amount"></p>

I guess using onChange this is possible. The number of checkbox should total depends on what fields check in checkbox and the amount should total based on amount column and fields that check in checkbox. It is possible?

Macky
  • 13
  • 4
  • Inline event handlers like `onclick` or `onchange` are [not recommended](https://stackoverflow.com/q/11737873/4642212). They are an [obsolete, hard-to-maintain and unintuitive](https://stackoverflow.com/a/43459991/4642212) way of registering events. Always [use `addEventListener`](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#inline_event_handlers_%E2%80%94_dont_use_these) instead. – Sebastian Simon Feb 16 '21 at 03:03
  • Use [event delegation](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_delegation) instead of assigning multiple events — it’s more maintainable, and applies to dynamically added elements. E.g., use an [event argument](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#The_event_listener_callback)’s [`target`](https://developer.mozilla.org/en-US/docs/Web/API/Event/target). See [the tag info](https://stackoverflow.com/tags/event-delegation/info) and [What is DOM Event delegation?](https://stackoverflow.com/q/1687296/4642212). – Sebastian Simon Feb 16 '21 at 03:04
  • @SebastianSimon Can you help me? I'm out of option I tried. – Macky Feb 16 '21 at 03:15
  • It’s a bit difficult to understand what the desired result is, but it seems like you’d like to count checkboxes and / or toggle a group of checkboxes. I’d probably do something like [this](https://jsfiddle.net/31cye4j5/). – Sebastian Simon Feb 16 '21 at 04:03

3 Answers3

1

If you wrap your checkboxes in a <form>, you can listen for a change event.

On that <form>'s change event, you can filter all your checkboxes to get just the ones that are checked. You can get the value of total_checked from this filtered array's length property.

If you add a class to your amount <td>, it will be easier to make the adjacent selection from the checkbox.

Here I've used checkbox.closest('tr').querySelector('.amount') to get the string value from the text within the adjacent <td>.

Looping through the checked checkboxes, you can keep a running total of the values, taking care to convert the strings to numbers.

const form = document.querySelector('form')
const mainCheckbox = document.querySelector('#main_checkbox')
let otherCheckboxes = document.getElementsByName('product_id[]')
const totalCheckedText = document.querySelector('#total_checked')
const totalAmountText = document.querySelector('#total_amount')


mainCheckbox.addEventListener('change', (event) => {
  otherCheckboxes.forEach(checkbox => {
    checkbox.checked = event.currentTarget.checked
  })
})

form.addEventListener('change', () => {
  const checked = Array.from(otherCheckboxes).filter(checkbox => checkbox.checked)
  let totalAmount = 0
  checked.forEach(checkbox => {
    const amount = Number(checkbox.closest('tr').querySelector('.amount').innerText) || 0
    totalAmount += amount
  })

  totalCheckedText.textContent = checked.length
  totalAmountText.textContent = totalAmount
})
<form>
  <table class="table" name="table" id="table">
    <thead>
      <tr>
        <th></th>
        <th><input id="main_checkbox" type="checkbox" /></th>
        <th>Name</th>
        <th>Amount</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td></td>
        <td><input type="checkbox" name="product_id[]"></td>
        <td>Jessica</td>
        <td class="amount">5200</td>
      </tr>

      <tr>
        <td></td>
        <td><input type="checkbox" name="product_id[]"></td>
        <td>Jessica</td>
        <td class="amount">800</td>
      </tr>
    </tbody>
  </table>
  Number of checkbox =
  <p id="total_checked"></p>
  Total amount =
  <p id="total_amount"></p>
</form>
ksav
  • 13,381
  • 5
  • 27
  • 51
1

This may help you to move forward

const toggle = (source) => {
  const checkboxes = document.getElementsByName('product_id[]');
  checkboxes.forEach(cb => {
    cb.checked = source.checked;
  });
  compute();
}

const compute = () => {
  const checkboxes = document.getElementsByName('product_id[]');
  let total = 0;
  let checked = 0;
  checkboxes.forEach(cb => {
    if (cb.checked) {
      checked++;
      const amountElt = cb.parentElement.parentElement.getElementsByClassName("amount")[0];
      total += parseInt(amountElt.innerText, 10);
    }
  });
  document.getElementById("total_checked").innerText = checked;
  document.getElementById("total_amount").innerText = total;


  if (checked === 0) {
    document.getElementById("selectall").checked = false;
  } else if (checked === checkboxes.length) {
    document.getElementById("selectall").checked = true;
  }
}

document.getElementsByName('product_id[]').forEach(cb => {
  cb.addEventListener('change', compute);
});
<table class="table" name="table" id="table">
  <thead>
    <tr>
      <th></th>
      <th><input id="selectall" type="checkbox" onClick="toggle(this)" /></th>
      <th>Name</th>
      <th>Amount</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td></td>
      <td><input type="checkbox" name="product_id[]"></td>
      <td>Jessica</td>
      <td class="amount">5200</td>
    </tr>

    <tr>
      <td></td>
      <td><input type="checkbox" name="product_id[]"></td>
      <td>Jessica</td>
      <td class="amount">800</td>
    </tr>
  </tbody>
</table>

<p>
Number of checkbox = <span id="total_checked"></span>
</p>
<p>
Total amount = <span id="total_amount"></span>
</p>
D. Seah
  • 4,091
  • 1
  • 8
  • 18
  • thanks for your response but my amount value is not in the lastelementchild can you help me to set the amount through assigning the ID? – Macky Feb 16 '21 at 05:41
  • can you fix your question to show where the amount is? – D. Seah Feb 16 '21 at 06:20
  • Thanks for your response, I've update my snippet and I just added another column in my table. it seems the total amount would be trigger in the last element of the table , but i want to trigger the amount without using lastelementchild since in my real table my amount is not place in the last, thanks in advance – Macky Feb 16 '21 at 06:26
  • is it always in the 4th column? otherwise, you need a class (or some thing) to locate it – D. Seah Feb 16 '21 at 06:29
  • thanks for your response Yes I think it's only define using class but how can I ? – Macky Feb 16 '21 at 06:38
  • I have updated my solution, please cross check. thanks – D. Seah Feb 16 '21 at 06:44
0

Run your elements through a loop and eventlistener then a conditional to check if the inputs are :checked if they are, increment/decrement the iterator to track the checked items and addition/subtraction of amounts.

let totalChecked = document.querySelector('#total_checked')
let totalAmount = document.querySelector('#total_amount')
let inputs = document.querySelectorAll('input')
let i = 0
let amount;
inputs.forEach( input =>{
  input.addEventListener('change', e => {
    if(e.target.checked){
      totalAmount.textContent = Number(totalAmount.textContent) + Number(e.target.parentNode.parentNode.children[2].textContent)
      i++;  
    }else{
      totalAmount.textContent = Number(totalAmount.textContent) - Number(e.target.parentNode.parentNode.children[2].textContent)
      i--;
    }
    totalChecked.textContent = i;    
  })
})
<table class="table" name="table" id="table">
  <thead>
    <tr>
      <th></th>
      <th>Name</th>
      <th class="amount">Amount</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><input type="checkbox"></td>
      <td>Jessica</td>
      <td class="amount">5200</td>
    </tr>

    <tr>
      <td><input type="checkbox"></td>
      <td>Jessica</td>
      <td class="amount">800</td>
    </tr>
  </tbody>
</table>
Number of checkbox = 
<p id="total_checked"></p>
Totol amount =
<p id="total_amount"></p>
dale landry
  • 3,942
  • 2
  • 12
  • 22
  • thanks for your answer I think this is the exact solution that I want but your missing checkall the checkbox in the header part, can you make checkbox in header check those checboxes? – Macky Feb 16 '21 at 05:35