0

I'm having this issue while trying to get values from my table ( these tds are generated on button click ) and classname added with

prdctNameSpace.className = 'subTotal';

This is my JS function

 var arr=document.getElementsByClassName('subTotal');
    console.log(arr.length);

var tot=0;
for(var i=0;i<arr.length;i++)
{
    tot += parseFloat(arr[i].value);
}
console.log(tot);

document.getElementById('totalprod').innerHTML = tot;

The output in my HTML is NaN . The first console.log() is working good because it keeps adding +1 everytime I add new . I just can't make the sum of these values.

var addShopList = function() {
  // Ajouter un element au tableau
  var product = document.getElementById("shopList").options[document.getElementById('shopList').selectedIndex].text;
  var quantity = document.getElementById("qte").value;
  var sum = document.getElementById("shopList").value;
  var total = parseInt(quantity) * parseFloat(sum);

  var tbody = document.querySelector('#sellTable tbody');
  var trproduct = document.createElement('TR');
  tbody.appendChild(trproduct);

  var tbodytr = tbody.lastChild;

  //Making 1st Row
  var prdctNameSpace = document.createElement('TD');
  tbodytr.appendChild(prdctNameSpace);
  //First Row content
  var prdctName = document.createTextNode(product);
  prdctNameSpace.appendChild(prdctName);
  prdctNameSpace.className = 'subTotal';

  var productQteSpace = document.createElement("TD");
  tbodytr.appendChild(productQteSpace);
  //2nd col Content
  var productQte = document.createTextNode(quantity);
  productQteSpace.appendChild(productQte);

  //3rd Col
  var productSinglePriceSpace = document.createElement("TD");
  tbodytr.appendChild(productSinglePriceSpace);
  var productSinglePrice = document.createTextNode(parseInt(sum).toFixed(3) + " DT");
  productSinglePriceSpace.appendChild(productSinglePrice);
  //4th col

  var productTotalPriceSpace = document.createElement("TD");
  tbodytr.appendChild(productTotalPriceSpace);
  var productTotalPrice = document.createTextNode(parseFloat(total).toFixed(3) + " DT");
  productTotalPriceSpace.appendChild(productTotalPrice);

  var productDeleteSpace = document.createElement("TD");
  var productDeletebtn = document.createElement("BUTTON");
  //tbodytr.appendChild(productDeleteSpace);

  productDeletebtn.setAttribute('class', 'btn x');
  productDeletebtn.name = 'delrow';
  productDeletebtn.textContent = "X";
  tbodytr.appendChild(productDeletebtn);
  console.log(productDeletebtn.name);
  productDeletebtn.setAttribute('onclick', 'delRowList(this)');


  var arr = document.getElementsByClassName('subTotal');
  console.log(arr.length);

  var tot = 0;
  for (var i = 0; i < arr.length; i++) {
    tot += parseFloat(arr[i].value);
  }
  console.log(tot);
  document.getElementById('totalprod').innerHTML = tot;
}

function emptyQte() {
  if (document.getElementById('qte').value === "") {
    document.getElementById('ajout').disabled = true;
  } else {
    document.getElementById('ajout').disabled = false;
  }
}

var delRowList = function(btn2) {
  var delbtn = document.getElementById('sellTable');
  delbtn.deleteRow(btn2.parentNode.rowIndex);
}

var setupListeners = function() {
  var btn = document.getElementById('ajout');
  btn.addEventListener('click', addShopList);
}

window.addEventListener('load', setupListeners);
<select id="shopList" onlick="summ()" class="form-select form-select-lg mb-3">
  <option selected disabled="disabled"> Liste Des Produits</option>
  <optgroup label="Femme">
    <option value="40" name="PullVegeta2"> Top Femme Colle V
  </optgroup>
  <optgroup label="Homme">
    <option value="35" name="PullVegeta3">Pull Homme OpenMinded
      <option value="30" name="PullVegeta">Pull Homme Vegeta

  </optgroup>
</select>
<input type="text" id="qte" placeholder="Quantité" onkeyup="emptyQte()" onkeypress="return (event.charCode == 8 || event.charCode == 0) ? null : event.charCode >= 48 && event.charCode <= 57" required/>
<input type="button" value="Ajouter" id="ajout" disabled>
<table id="sellTable" class="table">
  <thead>
    <tr>
      <th scope="col">Nom Produit</th>
      <th scope="col">Quantité</th>
      <th scope="col">Prix Unitaire</th>
      <th scope="col">Total Produit</th>
      <th scope="col">Action</th>
    </tr>
  </thead>
  <tbody>
  </tbody>

  <tfooter>
    <td colspan="3">Somme Total :</td>
    <td id="totalprod"> DT</td>
    <td> <button>Paiement</button></td>
  </tfooter>
</table>

Live Version : https://jsfiddle.net/ajkpo47L/

6
  • 2
    What is arr[i].value? Please also provide the associated HTML as a minimal reproducible example. Commented May 14, 2021 at 16:20
  • 2
    Can you make a live Stack Snippet illustrating the problem? There isn't enough information here to reproduce the issue. Commented May 14, 2021 at 16:20
  • More info is needed, specifically example data. Commented May 14, 2021 at 16:22
  • 1
    You need to check that arr[i].value is non-empty before adding it to the total. Commented May 14, 2021 at 16:23
  • 1
    Please don't use external code representations like fiddles, codepens etc. unless the StackOverflow snippet functionality isn't sufficient to demonstrate your issue. Questions seeking debugging help need to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem in the question itself. Commented May 14, 2021 at 16:42

4 Answers 4

3

prdctNameSpace is a <td>, not an <input>. It doesn't have a value property.

You should use .textContent rather than .value to get the contents.

Also, you're putting the subTotal class on the wrong element. You're putting it on the cell with the product name, not the total price of that product.

var addShopList = function() {
  // Ajouter un element au tableau
  var product = document.getElementById("shopList").options[document.getElementById('shopList').selectedIndex].text;
  var quantity = document.getElementById("qte").value;
  var sum = document.getElementById("shopList").value;
  var total = parseInt(quantity) * parseFloat(sum);

  var tbody = document.querySelector('#sellTable tbody');
  var trproduct = document.createElement('TR');
  tbody.appendChild(trproduct);

  var tbodytr = tbody.lastChild;

  //Making 1st Row
  var prdctNameSpace = document.createElement('TD');
  tbodytr.appendChild(prdctNameSpace);
  //First Row content
  var prdctName = document.createTextNode(product);
  prdctNameSpace.appendChild(prdctName);

  var productQteSpace = document.createElement("TD");
  tbodytr.appendChild(productQteSpace);
  //2nd col Content
  var productQte = document.createTextNode(quantity);
  productQteSpace.appendChild(productQte);

  //3rd Col
  var productSinglePriceSpace = document.createElement("TD");
  tbodytr.appendChild(productSinglePriceSpace);
  var productSinglePrice = document.createTextNode(parseInt(sum).toFixed(3) + " DT");
  productSinglePriceSpace.appendChild(productSinglePrice);
  //4th col

  var productTotalPriceSpace = document.createElement("TD");
  tbodytr.appendChild(productTotalPriceSpace);
  var productTotalPrice = document.createTextNode(parseFloat(total).toFixed(3) + " DT");
  productTotalPriceSpace.className = 'subTotal';
  productTotalPriceSpace.appendChild(productTotalPrice);

  var productDeleteSpace = document.createElement("TD");
  var productDeletebtn = document.createElement("BUTTON");
  //tbodytr.appendChild(productDeleteSpace);

  productDeletebtn.setAttribute('class', 'btn x');
  productDeletebtn.name = 'delrow';
  productDeletebtn.textContent = "X";
  tbodytr.appendChild(productDeletebtn);
  console.log(productDeletebtn.name);
  productDeletebtn.setAttribute('onclick', 'delRowList(this)');


  var arr = document.getElementsByClassName('subTotal');
  console.log(arr.length);

  var tot = 0;
  for (var i = 0; i < arr.length; i++) {
    console.log(arr[i].textContent);
    tot += parseFloat(arr[i].textContent);
  }
  console.log(tot);
  document.getElementById('totalprod').innerHTML = tot.toFixed(3) + ' DT';
}

function emptyQte() {
  if (document.getElementById('qte').value === "") {
    document.getElementById('ajout').disabled = true;
  } else {
    document.getElementById('ajout').disabled = false;
  }
}

var delRowList = function(btn2) {
  var delbtn = document.getElementById('sellTable');
  delbtn.deleteRow(btn2.parentNode.rowIndex);
}

var setupListeners = function() {
  var btn = document.getElementById('ajout');
  btn.addEventListener('click', addShopList);
}

window.addEventListener('load', setupListeners);
<select id="shopList" onlick="summ()" class="form-select form-select-lg mb-3">
  <option selected disabled="disabled"> Liste Des Produits</option>
  <optgroup label="Femme">
    <option value="40" name="PullVegeta2"> Top Femme Colle V
  </optgroup>
  <optgroup label="Homme">
    <option value="35" name="PullVegeta3">Pull Homme OpenMinded
      <option value="30" name="PullVegeta">Pull Homme Vegeta

  </optgroup>
</select>
<input type="text" id="qte" placeholder="Quantité" onkeyup="emptyQte()" onkeypress="return (event.charCode == 8 || event.charCode == 0) ? null : event.charCode >= 48 && event.charCode <= 57" required/>
<input type="button" value="Ajouter" id="ajout" disabled>
<table id="sellTable" class="table">
  <thead>
    <tr>
      <th scope="col">Nom Produit</th>
      <th scope="col">Quantité</th>
      <th scope="col">Prix Unitaire</th>
      <th scope="col">Total Produit</th>
      <th scope="col">Action</th>
    </tr>
  </thead>
  <tbody>
  </tbody>

  <tfooter>
    <td colspan="3">Somme Total :</td>
    <td id="totalprod"> DT</td>
    <td> <button>Paiement</button></td>
  </tfooter>
</table>

Sign up to request clarification or add additional context in comments.

2 Comments

inputs are filled by pressing a button which adds a td with some values and makes a total at the end
Yes , that was the problem. Thank you .
0

Instead of using parseFloat, I recommend using the Number()constructor, which, for an empty String, returns 0 instead of NaN:

const total = [...document.getElementsByClassName('subTotal')]
  .map(el=>el.value)
  .reduce((a, v) => a + Number(v), 0);

See this snippet for different results Number() vs. parseFloat():

const testValues = ['', null, undefined];

for (const value of testValues) {
  console.log(`Number(${value}) returns: ${Number(value)}`);
  console.log(`parseFloat(${value}) returns: ${parseFloat(value)}`);
}

1 Comment

still returning NaN , i guess the problem is with my arr variable , when I console.log(arr) is give me HTMLCollection . maybe using arr[i].value isn't right.
0

Your parseFloat function is likely returning NaN at some point.

let total = 0
for(const subTotalElem of document.getElementsByClassName('subTotal')) {
    const subTotal = Number.parseFloat(subTotalElem.value)
    if(Number.isNaN(subTotal)) {
      console.warn('Subtotal is not a number: ' + subTotalElem.value)
    } else {
      total += subTotal
    }
}
console.log('Total: ' + total)
<table>
  <tbody>
    <tr>
      <td>Parseable</td>
      <td><input disabled class="subTotal" value="42" /></td>
    </tr>
    <tr>
      <td>Parseable</td>
      <td><input disabled class="subTotal" value="42.00" /></td>
    </tr>
    <tr>
      <td>Parseable</td>
      <td><input disabled class="subTotal" value="42,00" /></td>
    </tr>
    <tr>
      <td>Not Parseable</td>
      <td><input disabled class="subTotal" value="$42.00" /></td>
    </tr>
    <tr>
      <td>Not Parseable</td>
      <td><input disabled class="subTotal" value="" /></td>
    </tr>
  </tbody>
</table>

Comments

0

I fixed it , sorry it was my fault. I put classname for my 1st td in the row , which contains name of product not the price.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.