0

I have a table to allow user to do multiple stock entry

<table class="table1" id="table1">
  <thread>
    <tr>
      <th scope="col">Item Name</th>
      <th scope="col">Qty</th>
      <th scope="col">Rate</th>
      <th scope="col">Amount</th>
    </tr>
  </thread>
  <tbody>
    <tr>
     <td><input type="text"/></td>
     <td><input type="text" class="num" id="qty"/></td>
     <td><input type="text" class="num" id="rate"/></td>
     <td><input type="text" class="num" id="amt"/></td>
   </tr>
 </tbody>
</table>
<a id="add"><button>Add</button></a>

And this code is to add a new row:

<script type="text/javascript">
  $(document).ready(function() {
    $("#add").click(function() {
      var newrow = $("<tr><td><input type="text"/></td><td><input type=\"text\" id=\"qty\"/></td><td><input type="\text\" id="\rate\"/></td><td><input type="\text\" id="\amt\"/></td></tr>");
    newrow.insertAfter('#table1 tbody>tr:last');
    return false;
  });
  $(".num").keyup(function() {
    var id = $(this).attr('id');
    if (id == 'qty') {
      var i = parseFloat($("#rate").val())
      if (!isNaN(i)) {
        var t = ($(this).val()*$("#rate").val());
        $("#amt").val(t.toFixed(2));
      } else {
        $("#amt").val('');
      }
    } else if (id == 'rate') {
      var i = parseFloat($("#qty").val())
      if (!isNaN(i)) {
        var t = ($(this).val()*$("#qty").val());
        $("#amt").val(t.toFixed(2));
      } else {
        $("#amt").val('');
      }
    }
  });
});

The calculation is working perfect on the first row of table, but when I am adding a second row the calculation is not working. Where I am wrong?

dda
  • 6,030
  • 2
  • 25
  • 34
Mandeep Singh
  • 2,016
  • 7
  • 19
  • 32

4 Answers4

5

Use event delegation:

$('body').on('keyup', ".num", function() {
    // your code
});

Also you must add class .num to your created elements, and you can't have the same ID for multiple elements, instead use another attribute (like data-id, it doesn't matter),

var newrow = $('<tr><td><input type="text" /></td><td><input type="text" class="num" data-id="qty"/></td><td><input type="text" data-id="rate"/></td><td><input type="text" class="num" data-id="amt" /></td></tr>');

And in your function get them with this attribute:

$('body').on('keyup', ".num", function() {
    var $row = $(this).closest('tr');
    var $amt = $row.find('[data-id="amt"]');
    var $qty = $row.find('[data-id="qty"]');
    var $rate = $row.find('[data-id="rate"]');

    var id = $(this).attr('data-id');

    if (id == 'qty') {
        // now using `$rate` instead of $('#rate')
        var i = parseFloat($rate.val())

        // other code
    }

    // other code
});
1

Give the new rows the num class (your new inputs don't have it), and use .on:

$(document).on('keyup', '.num', function() {

});

This is required if you want to add an event listener to elements that are not yet in the DOM.

Also, element IDs should be unique. Your new inputs are getting the same ID as the previous row.

MrCode
  • 63,975
  • 10
  • 90
  • 112
1

This issue can be solved via event delegation to the existing closet parent like in your case is $('#table1') or $(document) which is the parent of all the elements on a page, so you need to change this:

$(".num").keyup(function() {

to this:

$("#table").on('keyup', '.num', function() {

I just seen your additions you are adding same ids when clicked to add, so that results in a invalid html markup due to ids should be unique in the same page (same ids for multiple elems is invalid).

 var newrow = $("<tr><td><input type='text'/></td>"+
                "<td><input type='text' id='qty'/></td>"+
                "<td><input type='text' id='rate'/></td>"+
                "<td><input type='text' id='amt'/></td></tr>");

The above one everytime adds same id for multiple elements when added to the dom. you can try to do this way:

  $("#add").click(function () {
    var i = $("#table1 tbody>tr:last").index();
    var newrow = $("<tr><td><input type='text'/></td>" +
        "<td><input type='text' class='num' id='qty" + (i) + "'/></td>" +
        "<td><input type='text' class='num' id='rate" + (i) + "'/></td>" +
        "<td><input type='text' class='num' id='amt" + (i) + "'/></td>");
    newrow.insertAfter('#table1 tbody>tr:last');
    return false;
});     
Jai
  • 74,255
  • 12
  • 74
  • 103
0

try this

<table class="table1" id="table1">
        <thread>
    <tr>
      <th scope="col">Item Name</th>
      <th scope="col">Qty</th>
      <th scope="col">Rate</th>
      <th scope="col">Amount</th>
    </tr>
  </thread>
        <tbody>
            <tr>
                <td>
                    <input type="text" />
                </td>
                <td>
                    <input type="text" class="num" name="qty" id="qty" />
                </td>
                <td>
                    <input type="text" class="num" id="rate" name="rate" />
                </td>
                <td>
                    <input type="text" class="num" id="amt" name="amt" />
                </td>
            </tr>
        </tbody>
    </table>
    <a id="add">
        <button>
            Add</button></a>


     <script type="text/javascript">
    $(document).ready(function () {
        $("#add").click(function () {
            var newrow = $('<tr><td><input type="text"></td><td><input type="text" id="qty" name="qty" class="num"></td><td><input type="text" id="rate" name="rate" class="num"></td><td><input type="text" id="amt" name="amt" class="num"></td></tr>');
            newrow.insertAfter('#table1 tbody>tr:last');


            $('#table1 tbody>tr:last').find('[name="qty"]').keyup(function () {
                var this_tr = $(this).closest('tr');
                ;
                var i = parseFloat(this_tr.find('[name="rate"]').val())
                if (!isNaN(i)) {
                    var t = ($(this).val() * this_tr.find('[name="rate"]').val());
                    this_tr.find('[name="amt"]').val(t.toFixed(2));
                } else {
                    this_tr.find('[name="amt"]').val('');
                }
            });
            $('#table1 tbody>tr:last').find('[name="rate"]').keyup(function () {
                var this_tr = $(this).closest('tr');
                ;
                var i = parseFloat(this_tr.find('[name="qty"]').val())
                if (!isNaN(i)) {
                    var t = ($(this).val() * this_tr.find('[name="qty"]').val());
                    this_tr.find('[name="amt"]').val(t.toFixed(2));
                } else {
                    this_tr.find('[name="amt"]').val('');
                }
            });
            return false;
        });
        $('[name="qty"]').keyup(function () {
            var this_tr = $(this).closest('tr');
            ;
            var i = parseFloat(this_tr.find('[name="rate"]').val())
            if (!isNaN(i)) {
                var t = ($(this).val() * this_tr.find('[name="rate"]').val());
                this_tr.find('[name="amt"]').val(t.toFixed(2));
            } else {
                this_tr.find('[name="amt"]').val('');
            }
        });
        $('[name="rate"]').keyup(function () {
            var this_tr = $(this).closest('tr');
            ;
            var i = parseFloat(this_tr.find('[name="qty"]').val())
            if (!isNaN(i)) {
                var t = ($(this).val() * this_tr.find('[name="qty"]').val());
                this_tr.find('[name="amt"]').val(t.toFixed(2));
            } else {
                this_tr.find('[name="amt"]').val('');
            }
        });

    });
</script>
sangram parmar
  • 8,462
  • 2
  • 23
  • 47