skip to Main Content

I’m struggling to read and manipulate data from an HTML form in Javascript/Jquery.

Context: I have a sales screen showing multiple products, and I want to loop through them all, analyze their contents, and present some of the data in a shopping cart.

Please forgive my lack of knowledge in JS!!

Consider this HTML code (the complete form has a lot more variables for each product, so I’ve simplified it here):

  <input type='text' name='sales[1][qty]' value='10.5' />
  <input type='text' name='sales[1][price]' value='21' />
  <input type='text' name='sales[1][name]' value='Product A' />
  <input type='hidden' name='sales[1][purchaseid]' value='3530' />
  
  <input type='text' name='sales[2][qty]' value='' />
  <input type='text' name='sales[2][price]' value='' />
  <input type='text' name='sales[2][name]' value='Product B' />
  <input type='hidden' name='sales[2][purchaseid]' value='3531' />
  
  <input type='text' name='sales[3][qty]' value='2' />
  <input type='text' name='sales[3][price]' value='10' />
  <input type='text' name='sales[3][name]' value='Product C' />
  <input type='hidden' name='sales[3][purchaseid]' value='3532' />
  
  <input type='text' name='sales[4][qty]' value='' />
  <input type='text' name='sales[4][price]' value='' />
  <input type='text' name='sales[4][name]' value='Product D' />
  <input type='hidden' name='sales[4][purchaseid]' value='3533' />

When someone clicks the Cart button, I want to loop over all entries in the sales[][] array, and display only products whose ‘qty’ or ‘price’ is not blank. The flow would be something like this:

  1. Loop through all sales[][qty] and sales[][price] values. If either is not blank, return the key in sales[].

  2. In the HTML code above, only products sales[1] and sales[3] have these values. So I want to return 1 and 3.

  3. Read the data from those keys and present it in a HTML table. So for example, as only keys 1 and 3 are not blank, I want to read the values of sales[1][qty], sales[1][price], sales[1][name], sales[1][purchaseid] – and the values of sales[3][qty], sales[3][price], sales[3][name], sales[3][purchaseid].

  4. Present them in an HTML table, like below:

     <table>
    <tr>
     <td>ID</td>
     <td>Name</td>
     <td>Quantity</td>
     <td>Price</td>
    </tr>
    <tr>
     <td>3530</td>
     <td>Product A</td>
     <td>10.5</td>
     <td>21</td>
    </tr>
    <tr>
     <td>3532</td>
     <td>Product C</td>
     <td>2</td>
     <td>10</td>
    </tr>
    

I can do this easily in PHP when the form is submitted – but the idea here is to NOT submit the form, meaning JS has to do the job. In PHP I would do it along these lines:

        foreach($_POST['sales'] as $sale) {
        
        $qty = $sale['qty'];
        $price = $sale['price'];
        $name = $sale['name'];
        $purchaseid = $sale['purchaseid'];
        
        if ($qty > 0 || $price > 0) {
            
            $tableRow .= "<tr><td>$purchaseid</td><td>$name</td><td>$qty</td><td>$price</td></tr>";
            
        }
        
    }

I’ve searched and found out how to simply grab names and values from a HTML form by using the below code, but it doesn’t help with my points 2 and 3 above:

    function testCart() {
    
    var str = '';
    var elem = document.getElementById('registerForm').elements;
    
    for(var i = 0; i < elem.length; i++)
    {
                str += "<b>Name:</b>" + elem[i].name + " - ";
                str += "<b>Value:</b>" + elem[i].value + "<br />";
    }
    
    document.getElementById('myCart').innerHTML = str;
    
}

Can someone please give me any pointers on how to proceed with this?

Thank you!

2

Answers


  1. One way would be to simply use dynamic attribute selectors in a loop.

    We try and find the field with name='sales[1][qty]' first, and if that exists, we check if that value is not empty and read the corresponding other field values for that same index.

    I put a simple console.log statement to show the values in the browser console here – that part you will have to replace with actually populating a table with that data.

    At the end of the loop we increase the index by one, and try to find the next quantity field in the next iteration. As soon as we don’t find one any more, it is time to break off the loop.

    let i = 1;
    while (true) {
      let qtyField = document.querySelector('[name="sales[' + i + '][qty]"]');
      if (!qtyField) {
        break;
      }
    
      let qty = qtyField.value,
        name = document.querySelector('[name="sales[' + i + '][name]"]').value,
        price = document.querySelector('[name="sales[' + i + '][price]"]').value,
        id = document.querySelector('[name="sales[' + i + '][purchaseid]"]').value;
      if (qty != '' || price != '') {
    
        console.log("Product:", id, name, price, qty);
      }
      ++i;
    }
    <input type='text' name='sales[1][qty]' value='10.5' />
    <input type='text' name='sales[1][price]' value='21' />
    <input type='text' name='sales[1][name]' value='Product A' />
    <input type='hidden' name='sales[1][purchaseid]' value='3530' />
    
    <input type='text' name='sales[2][qty]' value='' />
    <input type='text' name='sales[2][price]' value='1' />
    <input type='text' name='sales[2][name]' value='Product B' />
    <input type='hidden' name='sales[2][purchaseid]' value='3531' />
    
    <input type='text' name='sales[3][qty]' value='2' />
    <input type='text' name='sales[3][price]' value='10' />
    <input type='text' name='sales[3][name]' value='Product C' />
    <input type='hidden' name='sales[3][purchaseid]' value='3532' />
    
    <input type='text' name='sales[4][qty]' value='' />
    <input type='text' name='sales[4][price]' value='' />
    <input type='text' name='sales[4][name]' value='Product D' />
    <input type='hidden' name='sales[4][purchaseid]' value='3533' />
    Login or Signup to reply.
  2. This is another approach using jQuery and looping through input elements having the name attribute set as sales followed by [#][qty] or [#][price].

    It’s a waste of efforts frankly speaking because there’s no gap expected between indexes and for those elements they are supposed to be a contiguous list of numbers.

    $(document).ready(function() {
        var validSales = [];
    
        //the most safest approach to loop through elements having name attr starting by sales[
        $("input[name^='sales[']").each(function() {
            
            var name = $(this).attr('name');
            var match = name.match(/sales[(d+)][(qty|price)]/);
            
            //check if the name attribute actually refers to the indexes qty or price, and the corresponding element value is set
            if (match) {
                var index = match[1];
                if ($(this).val() && !validSales.includes(index)) {
                    //if it does, push the index into the validSales array
                    validSales.push(index);
                }
            }
        });        
    
        //now for each index pushed into validSales
        validSales.forEach(function(index) {
            //retrieves the values of qty, price, name, purchaseid belonging to such id
            var qty = $(`input[name='sales[${index}][qty]`).val();
            var price = $(`input[name='sales[${index}][price]`).val();
            var name = $(`input[name='sales[${index}][name]`).val();
            var purchaseid = $(`input[name='sales[${index}][purchaseid]`).val();                        
            
            var row = `<tr><td>${purchaseid}</td><td>${name}</td><td>${qty}</td><td>${price}</td></tr>`;
            $("#myCart").append(row);
        });
    });
    table#myCart{
      margin-top: 1em;
    }
    
    table#myCart td{
      border: solid 1px;
    }
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    
    <input type='text' name='sales[1][qty]' value='10.5' />
    <input type='text' name='sales[1][price]' value='21' />
    <input type='text' name='sales[1][name]' value='Product A' />
    <input type='hidden' name='sales[1][purchaseid]' value='3530' />
    
    <input type='text' name='sales[2][qty]' value='' />
    <input type='text' name='sales[2][price]' value='' />
    <input type='text' name='sales[2][name]' value='Product B' />
    <input type='hidden' name='sales[2][purchaseid]' value='3531' />
    
    <input type='text' name='sales[3][qty]' value='2' />
    <input type='text' name='sales[3][price]' value='10' />
    <input type='text' name='sales[3][name]' value='Product C' />
    <input type='hidden' name='sales[3][purchaseid]' value='3532' />
    
    <input type='text' name='sales[4][qty]' value='' />
    <input type='text' name='sales[4][price]' value='' />
    <input type='text' name='sales[4][name]' value='Product D' />
    <input type='hidden' name='sales[4][purchaseid]' value='3533' />
    
    <!-- myCart table element -->
    <table id="myCart">
      <tr>
        <td>qty</td>
        <td>price</td>
        <td>name</td>
        <td>purchaseid</td>
      </tr>
    </table>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search