Reputation: 635
I have a table that i can insert new row after click on a button. I would like to use a keyup function to make calcul between td values. My issue is the keyup function works for the first line, after I insert a new line the function affects the new line and previous line. How can I create the function to use it separately for each new row added ?
Thanks in advance.
<button type="button" class="add-row" >Add</button>
<table>
<tr>
<td>Amount</td>
<td>Price</td>
<td>Result</td>
</td>
</tr>
<tr>
<td class='amount' contenteditable='true'></td>
<td class='price' contenteditable='true' onkeyup='calculfac()'></td>
<td class='result'></td>
</tr>
</table>
<script>
//Add new row on click
$(".add-row").click(function(){
var markup = "<tr><td class='amount' contenteditable='true'></td><td class='price' contenteditable='true' onkeyup='calculfac()'></td><td class='result'></td></tr>";
$("table tbody").append(markup);
});
//Calcul
function calculfac() {
var amount= $('.amount').text();
var price= $('.price').text();
var mult = amount * price;
var result = Math.round(mult).toFixed(2);
$('.result').text(result);
}
Upvotes: 1
Views: 2043
Reputation: 2927
You're almost there in your snippet. You can specify a parent when using creating jQuery selector: $('.selector', parent)
where parent
can be a jQuery object or another selector itself. See the snippet below:
function calculfac() {
const parent = $(this).parent('tr');
const amount = $('.amount', parent).text();
const price = $('.price', parent).text();
const result = Math.round(amount * price).toFixed(2);
$('.result', parent).text(result);
}
Additionally I would remove onkeyup="calculfac()"
from your elements and use a jQuery selector and pass in your function as the handler. This allows us to trigger the event on each editable zone instead of just the price. If we do not do this a user could set the price and later update the amount but the total would remain the same before the change. See the snippet below:
$('tbody').on('keyup', '[contenteditable="true"]', calculfac);
A key difference about the above snippet is we're using .on
. Since the new tr
's are generated by your click
handler a traditional selector of tr [contenteditable="true"]
won't work as the new tr
from your handler do not yet exist in the DOM at the time the selector is ran. .on
allows you to filter a wider range of elements. So we're selecting tbody
and on keyup
of matching contenteditable=true
elements we're passing the event to our calculfac
function.
Here is the complete Fiddle
Upvotes: 2
Reputation: 344
That's because you're working with classes. Your code can't recognize which class value should change. It will change all the values of all classnames.
You can fix it by using the .each()
function. You want to change the contents of the <td>
tags in almost each <tr>
tag. Not every <tr>
tag so we can use a class to tell which <tr>
we mean. So, lets go:
Step 1 - Add the class '.tr' at the tags that have the children that you want to change.
<tr class="tr">
Step 2 - Add the '.tr' class to the 'Add new row' - function
//Add new row on click
$(".add-row").click(function(){
var markup = "<tr class='tr'><td class='amount' contenteditable='true'></td><td class='price' contenteditable='true' onkeyup='calculfac()'></td><td class='result'></td></tr>"; //Add '.tr' class
$("table tbody").append(markup);
});
Step 3 - Tell the classes that you want to get/change the values of them on each .tr class.
function calculfac() {
$('.tr').each(function(){ //Each .tr class
var amount= $('.amount', this).text(); //The .amount class of 'this' .tr class
var price= $('.price', this).text(); //The .price class of 'this' .tr class
var mult = amount * price;
var result = Math.round(mult).toFixed(2);
$('.result', this).text(result); //The .results class of 'this' .tr class
});
}
Example
Check out the JSFiddle: https://jsfiddle.net/z9qsyzr8/15/
Upvotes: 1