简体   繁体   中英

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

You need to use .each :

var listItems = $("#productList li");
listItems.each(function(idx, li) {
    var product = $(li);

    // and the rest of your code
});

This is the correct way to loop through a jQuery selection.


In modern Javascript you can also use a for .. of loop:

var listItems = $("#productList li");
for (let li of listItems) {
    let product = $(li);
}

Be aware, however, that older browsers will not support this syntax, and you may well be better off with the jQuery syntax above.

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?

Try this:

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

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
}

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));

    });

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; ie 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 (ie 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

   <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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM