dreamyrhodes dreamyrhodes - 6 months ago 11
jQuery Question

Work on current childs of a table row instead of all elements of name or class

I need help limiting a jQuery function to a certain table row instead of working on all elements of a class/name. I could use IDs here, if I knew how to get an unique ID of a after it was added. Since I would have to create the ID unique each time I add a field, I don't think that this would be an easy and elegant way. So I am looking for how use find() the right way to get the exact parent of the child input field I worked on or a different, maybe more sophisticated way of selecting the parent.

With the help of other questions asked here, I have created the following code:
A table in a form that looks like this

<table>
<tr>
</tr>
<tr class="service_list">
<td><a href="#" onclick="add_row();">+</a></td>
</tr>
</table>


The function "add_row()" that adds a row to the table

function add_row()
{
$('table tr.service_list:last').after('<tr>\
<td>\
<select class="profile service" name="service_list[]">\
<option value="50">service50</option>\
<option value="100">service100</option>\
</select>\
</td>\
<td>\
<input type="text" name="rate[]" value="1" />\
</td>\
<td>\
<input type="text" name="single_price[]" value="50" \>\
</td>\
<td>\
<input type="text" name="total[]" value="50" />\
</td>\
</tr>');
}


When the user changes the select field, thanks to the "attributeStartsWith" selector this jQuery is triggered

$(document).on('change', 'select', function(e) {
var value = $('select[name^=service_list]').val();
var rate = $('input[name^=rate]').val();
var total = value*rate;
$('[name^=single_price]').val(value);
$('input[name^=total]').val(total)
});


And when the "rate" field is changed, this will be triggered calculating the total price

$(document).on('input', '[name^=rate]', function(e) {
var rate = $('input[name^=rate]').val();
var orig_price = $('[name^=single_price]').val();

var total = orig_price * rate;

$('[name^=total]').val(total);
});


Of course as it is now, the value of all fields name starting "total" gets changed. Same would happen, if I used classes.

Answer

You need to use jQuery DOM traversal methods to find the elements you want within the same tr as the element which raised the event. In this case, you can use closest() and find(), like this:

$(document).on('change', 'select', function(e) {
    var $row = $(this).closest('tr');
    var value = $row.find('select[name^=service_list]').val();
    var rate = $row.find('input[name^=rate]').val();
    var total = value * rate;    
    $row.find('[name^=single_price]').val(value);
    $row.find('input[name^=total]').val(total)
});

$(document).on('input', '[name^=rate]', function(e) {
    var $row = $(this).closest('tr');
    var rate = $row.find('input[name^=rate]').val();
    var orig_price = $row.find('[name^=single_price]').val();    
    var total = orig_price * rate;    
    $row.find('[name^=total]').val(total);
});

Note that you may see better performance from your code by using classes over the 'attribute begins with' selector.