-5

How to auto sum all row in dynamic input fields in table?

I'm trying to sum up all the rows dynamically using JavaScript but my problem is that calcsum() function is not working and it does not print anything in add total textbox.
What update do I need in my calcsum() function?
I know my error is in the calcsum() function but I don't know how to solve it.

<HTML>

<HEAD>
  <TITLE> Add/Remove dynamic rows in HTML table </TITLE>
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

  <SCRIPT language="javascript">
    function addRow(tableID) {
      var table = document.getElementById(tableID);
      var rowCount = table.rows.length;
      if (rowCount < 4) { // limit the user from creating fields more than your limits
        var row = table.insertRow(rowCount);

        var colCount = table.rows[0].cells.length;
        row.id = 'row_' + rowCount;
        for (var i = 0; i < colCount; i++) {
          var newcell = row.insertCell(i);
          newcell.outerHTML = table.rows[0].cells[i].outerHTML;
        }
        var listitems = row.querySelectorAll("input, select");

        for (i = 0; i < listitems.length; i++) {
          listitems[i].setAttribute("oninput", "calculate('" + row.id + "')");
        }

      } else {
        alert("Maximum Passenger per ticket is 4.");

      }
    }



    function calculate(elementID) {
      var mainRow = document.getElementById(elementID);
      var myBox1 = mainRow.querySelectorAll('[name=qty]')[0].value;
      var myBox3 = mainRow.querySelectorAll('[name^=sel]')[0].value;
      var total = mainRow.querySelectorAll('[name=total]')[0];
      var myResult1 = myBox1 * myBox3;
      total.value = myResult1;

    }

    function calcsum(numberOfDivs) {
      var sum = 0;
      for (var i = 0; i < numberOfDivs; i++) {
        sum += parseInt(document.getElementsById('elementID' + i)[0].value);
      }
      return sum;


    }
  </SCRIPT>
</HEAD>

<BODY>
  <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
  <input type="button" value="Add" onClick="addRow('dataTable')" />

  <table id="dataTable" class="form" border="1">
    <tbody>
      <tr id='row_0'>
        <p>
          <td>
            <label>Quantity</label>
            <input type="number" required="required" name="qty" oninput="calculate('row_0')">
          </td>

          <td>
            <label for="sel">Price</label>
            <select name="sel" id="sel" oninput="calculate('row_0')" required>
              <option value="" disabled selected>Choose your option</option>
              <option value="1">1</option>
              <option value="2">2</option>
              <option value="3">3</option>
              <option value="4">4</option>
              <option value="5">5</option>
              <option value="6">6</option>
              <option value="7">7</option>
              <option value="8">8</option>
              <option value="9">9</option>
              <option value="10">10</option>
            </select>
          </td>
          <td>
            <label for="total">Total</label>
            <input type="text" required="required" class="small" name="total">
          </td>
        </p>
      </tr>
    </tbody>
  </table>
  add total<input type="text" oninput="calcsum()" name="anstotal">
</BODY>

</HTML>
Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
Misha
  • 9
  • 1
  • 8

3 Answers3

1

The error - one of the errors - comes from here document.getElementsById('elementID' + i)[0]. It is document.getElementById(…) with no s and it returns a single element and not a collection (which make perfect sense since ids are unique). The correct line should be document.getElementById('elementID' + i)

Cedric Cholley
  • 1,956
  • 2
  • 9
  • 15
0

You have calcsum taking a parameter that you never pass it. You need to do some sort of query selection to gather all the elements you need to add together, then get the value within those elements.

This post might help with that. Also, since you need to get all of the divs, you'll likely want to loop in some manor. The answer Here gives a way to go about that.

Most frameworks give some quality of life features of being able to store variables that you can display in the dom/html in a javascript file, which makes this process a bit easier. These posts show how you would do it in plain JS though.

iamaword
  • 1,327
  • 8
  • 17
0

Other answers told you what was wrong. I suggest to delegate and only have one place to handle the changes, that solves the problems and removed all the inline handlers

I removed the calculate and calculate on all changes

Also IDs must be unique, so I wrapped the labels around the elements

Lastly I clone the first row of the tbody instead of looping the cells

const makeNum = str => isNaN(str) || str.trim() === "" ? 0 : +str;
window.addEventListener("load", function() {
  const table = document.getElementById("dataTable");
  const tbody = table.querySelector("tbody");
  const grandTotal = document.querySelector("[name=anstotal]");
  tbody.addEventListener("input", function(e) {
    var sum = 0;
    [...tbody.querySelectorAll("tr")].forEach(row => {
      const qty = makeNum(row.querySelector("[name=qty]").value);
      const price = makeNum(row.querySelector("[name=sel]").value);
      const total = qty * price
      sum += total;
      row.querySelector("[name=total]").value = total.toFixed(2);
    })
    grandTotal.value = sum.toFixed(2);
  })

  document.getElementById("add").addEventListener("click", function() {
    const rowCount = table.rows.length;
    if (rowCount >= 4) {
      // limit the user from creating fields more than your limits
      alert("Maximum Passenger per ticket is 4.");
      return;
    }
    const newRow = tbody.querySelector("tr").cloneNode(true)
    newRow.id = "row"+rowCount;
    tbody.appendChild(newRow)
  })
})
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>

<input type="button" value="Add" id="add" />

<table id="dataTable" class="form" border="1">
  <tbody>
    <tr id='row_0'>
      <p>
        <td>
          <label>Quantity</label>
          <input type="number" required="required" name="qty">
        </td>

        <td>
          <label>Price
          <select name="sel"  required>
            <option value="" disabled selected>Choose your option</option>
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
            <option value="4">4</option>
            <option value="5">5</option>
            <option value="6">6</option>
            <option value="7">7</option>
            <option value="8">8</option>
            <option value="9">9</option>
            <option value="10">10</option>
          </select></label>
        </td>
        <td>
          <label>Total <input type="text" required="required" class="small" name="total"></label>
        </td>
      </p>
    </tr>
  </tbody>
</table>
add total<input type="text" name="anstotal">
mplungjan
  • 169,008
  • 28
  • 173
  • 236