Search code examples
javascriptcheckboxsumchecked

I want to sum numbers when a checkbox is checked in javascript


I want to sum the numbers and print them out in the span, i tried with innerHTML but as it is a string i can't, i tried parseInt, parseFloat, Number and nothing. For all the checkbox checked i want the sum of it's values into the span and those who are not checked i don't want them to get summ in the span

(i reduced the table and a lot of numbers because it's so long for putting it in here, so imagine that i want to sum a lot of total numbers)

const offersCheckbox = document.querySelectorAll("#checkbox-offers");
const recalculateText = document.querySelector(".recalculate-text");
const checkboxTotal = document.querySelectorAll("#checkbox-total");
let total = 0;

for (let i = 0; i < offersCheckbox.length; i++) {
  offersCheckbox[i].addEventListener("click", (e) => {
    if (offersCheckbox[i].checked === true) {
      recalculateText.innerHTML = "recalculate invoice total";
    } else {
      recalculateText.innerHTML = "";
    }
  });
}
<table>
  <tr>
    <tr>
      <td>
        <input type="checkbox" name="checkbox" id="checkbox-offers" value="2,434.38" />
        <td>
          <div class="price-container text-bold" id="checkbox-total">
            <b>$</b>2,434.38
          </div>
        </td>
    </tr>

    <tr>
      <td>
        <input type="checkbox" name="checkbox" id="checkbox-offers" value="76.69" />
      </td>
      <td>
        <div class="price-container text-bold" id="checkbox-total">
          <b>$</b>76.69
        </div>
      </td>
    </tr>
</table>

<span class="recalculate-text text-right text-underline"></span>


Solution

  • I didnt change too much from your original code. See the comments to understand the changes I made and feel free to comment if you have additional questions.

    const recalculateText = document.querySelector(".recalculate-text");
    const checkboxContainer = document.querySelector("#checkbox-container");
    let total = 0;
    
    // Create a number formatter to print out on the UI - this is a better approach than regex IMO.
    const formatter = new Intl.NumberFormat('en-US', {
      style: 'currency',
      currency: 'USD'
    });
    
    //Notice the use of event delegation here - meaning I only added 1 single event handler to a single DOM element
    //Read this blog for more on event delegation and why it's useful: https://davidwalsh.name/event-delegate
    checkboxContainer.addEventListener('change', e => {
      //Also notice that I am listening for the change event, instead of the click event.
      //See here: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event
      if (e.target.tagName == "INPUT") {
        const floatValue = parseFloat(e.target.value);
        if (e.target.checked) {
          total += floatValue;
        } else {
          total -= floatValue;
        }
      }
    
      recalculateText.innerHTML = formatter.format(total);
    });
    <!-- Notice I added a parent div to enable use to use event delegation technique -->
    <!-- Also notice I removed element id attributes where they were not needed. Also be sure
    to always use unique id values for every element - duplicate ids are not allowed, it will 
    lead to bugs. If elements need to be considered part of the same "group" then you should use
    the class attribute. -->
    <div id="checkbox-container">
      <table>
        <tr>
          <tr>
            <td>
              <!-- Notice I removed the comma from the value attribute -->
              <input type="checkbox" name="checkbox" value="2434.38" />
              <td>
                <div class="price-container text-bold">
                  <b>$</b>2,434.38
                </div>
              </td>
          </tr>
    
          <tr>
            <td>
              <input type="checkbox" name="checkbox" value="76.69" />
            </td>
            <td>
              <div class="price-container text-bold">
                <b>$</b>76.69
              </div>
            </td>
          </tr>
      </table>
    </div>
    <span class="recalculate-text text-right text-underline"></span>