[javascript] Looping through list items with jquery

I have this block of code

listItems = $("#productList").find("li");

        for (var li in listItems) {
            var product = $(li);
            var productid = product.children(".productId").val();
            var productPrice = product.find(".productPrice").val();
            var productMSRP = product.find(".productMSRP").val();

            totalItemsHidden.val(parseInt(totalItemsHidden.val(), 10) + 1);
            subtotalHidden.val(parseFloat(subtotalHidden.val()) + parseFloat(productMSRP));
            savingsHidden.val(parseFloat(savingsHidden.val()) + parseFloat(productMSRP - productPrice));
            totalHidden.val(parseFloat(totalHidden.val()) + parseFloat(productPrice));

        }

and I'm not getting the desired results - totalItems is coming out as 180+ and the rest all NaN. I suspect its where i use var product = $(li); or perhaps with the expression on the loop itself. Either way - I need to loop through the <li> items in the <ul> labelled #productList

This question is related to javascript jquery

The answer is


Try this code. By using the parent>child selector "#productList li" it should find all li elements. Then, you can iterate through the result object using the each() method which will only alter li elements that have been found.

listItems = $("#productList li").each(function(){

        var product = $(this);
        var productid = product.children(".productId").val();
        var productPrice = product.find(".productPrice").val();
        var productMSRP = product.find(".productMSRP").val();

        totalItemsHidden.val(parseInt(totalItemsHidden.val(), 10) + 1);
        subtotalHidden.val(parseFloat(subtotalHidden.val()) + parseFloat(productMSRP));
        savingsHidden.val(parseFloat(savingsHidden.val()) + parseFloat(productMSRP - productPrice));
        totalHidden.val(parseFloat(totalHidden.val()) + parseFloat(productPrice));

    });

   <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
   <script>
      $(document).ready(function() {
      $("form").submit(function(e){
          e.preventDefault();
       var name = $("#name").val();
       var amount =$("#number").val();
       var gst=(amount)*(0.18);
           gst=Math.round(gst);

       var total=parseInt(amount)+parseInt(gst);
       $(".myTable tbody").append("<tr><td></td><td>"+name+"</td><td>"+amount+"</td><td>"+gst+"</td><td>"+total+"</td></tr>");
       $("#name").val('');
       $("#number").val('');

       $(".myTable").find("tbody").find("tr").each(function(i){
       $(this).closest('tr').find('td:first-child').text(i+1);

       });

       $("#formdata").on('submit', '.myTable', function () {

                   var sum = 0;

          $(".myTable tbody tr").each(function () {
                    var getvalue = $(this).val();
                    if ($.isNumeric(getvalue))
                     {
                        sum += parseFloat(getvalue);
                     }                  
                     });

                     $(".total").text(sum);
        });

    });
   });

   </script>

     <style>
           #formdata{
                      float:left;
                      width:400px;
                    }

     </style>
  </head>


  <body>  

       <form id="formdata">  

                           <span>Product Name</span>
                           <input type="text" id="name">
                            <br>

                           <span>Product Amount</span>
                           <input type="text" id="number">
                           <br>
                           <br>
                           <center><button type="submit" class="adddata">Add</button></center>
       </form>
       <br>
       <br>

      <table class="myTable" border="1px" width="300px">
      <thead><th>s.no</th><th>Name</th><th>Amount</th><th>Gst</th><th>NetTotal</th></thead>

      <tbody></tbody>

      <tfoot>
             <tr>
                 <td></td>
                 <td></td>
                 <td></td>
                 <td class="total"></td>
                 <td class="total"></td>
             </tr>

      </tfoot>
      </table>

   </body>


For a more definitive answer, you'll need to post some of your markup. You can simplify your jQuery quite a bit, like the following:

$("#productList li").each(function() {
    var product = $(this);
    var productid = $(".productId", product).val();
    var productPrice = $(".productPrice", product).val();
    var productMSRP = $(".productMSRP", product).val();

    // the rest remains unchanged
}

To solve this without jQuery .each() you'd have to fix your code like this:

var listItems = $("#productList").find("li");
var ind, len, product;

for ( ind = 0, len = listItems.length; ind < len; ind++ ) {
    product = $(listItems[ind]);

    // ...
}

Bugs in your original code:

  1. for ... in will also loop through all inherited properties; i.e. you will also get a list of all functions that are defined by jQuery.

  2. The loop variable li is not the list item, but the index to the list item. In that case the index is a normal array index (i.e. an integer)

Basically you are save to use .each() as it is more comfortable, but espacially when you are looping bigger arrays the code in this answer will be much faster.

For other alternatives to .each() you can check out this performance comparison: http://jsperf.com/browser-diet-jquery-each-vs-for-loop


Try this:

listItems = $("#productList").find("li").each(function(){
   var product = $(this);
   // rest of code.
});

You can use each for this:

$('#productList li').each(function(i, li) {
  var $product = $(li);  
  // your code goes here
});

That being said - are you sure you want to be updating the values to be +1 each time? Couldn't you just find the count and then set the values based on that?