Onchange event in dynamic table html - javascript

My requirement is I have a table having 4 columns
in first cloumn can select item name, second is item rate, third is item qty last one is the total amount
I want to get the item rate automaticaly in second column while changing item in first, and want tom get the total after focus out from qty field as the multiple opf qty and rate,
i want a row adding buton to add rows and the onchange and onblur event should working on all rows,
how can i do this ?
my coode is
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
<script src="https://cdn.datatables.net/1.10.15/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.10.15/js/dataTables.bootstrap.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.6.4/css/bootstrap-datepicker.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.6.4/js/bootstrap-datepicker.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"/>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<table id="item_table">
<tr><th>SL No</th><th>Item Name</th><th>Rate</th><th>Qty</th><th>Total</th><th><button type="button" name="add" class="btn btn-success btn-sm add" >add</button></tr>
</table>
<script>
$(document).ready(function(){
$(document).on('click', '.add', function(){
var html = '';
html += '<tr>';
html += '<td><input type="text" name="slno[]" /></td>';
html += '<td><select name="item[]" id=item[] onchange="show_rate()"><option value="10">Item 1</option><option value="20">Item 2</option><option value="30">Item 3</option><option value="35">Item 4</option></td>';
html += '<td><input type="text" name="rate[]" id="rate[]" /></td>';
html += '<td><input type="text" name="qty[]" id="qty[]" onblur="sum_total()"/></td>';
html += '<td><input type="text" name="total[]" id="total[]" /></td>';
html += '<td><button type="button" name="remove" class="btn btn-danger btn-sm remove" >Remove</button></td></tr>';
$('#item_table').append(html);
});
$(document).on('click', '.remove', function(){
$(this).closest('tr').remove();
});
});
function show_rate(){
var a=document.getElementsByName("item[]")[0].value;
var b=document.getElementById("rate[]");
b.value=a;
}
function capitalise(){
var c=document.getElementsByName("rate[]")[0].value;
var d=document.getElementsByName("qty[]")[0].value;
var e=document.getElementById("total[]");
e.value=+c * +d;
}
</script>

You must make your select with values in the option tags. Each option must have a unique ID or name. You can then call upon the value attribute of the option and display it in column 2. Then use simple math operators to take the value and multiply it by a set variable, which you can also get from a select by using the mentioned above method. Example 12
Look at other posts for questions about adding rows, there are tons of posts out there on that topic with exactly the code you need.

Related

Adding new input using Jquery breaks tooltips

I'm writing a form and I have to let the user add as many rows as required.
As you can see, my inputs are treated as arrays to later save the data to the DB. (That will be another new thing to me)
$(document).ready(function() {
var maxField = 10; //Input fields increment limitation
var addButton = $('.add_button'); //Add button selector
var wrapper = $('.field_wrapper'); //Input field wrapper
var fieldHTML = '<tr> <td><input type="text" id="NombreProyecto" name="NombreProyecto[]"></td> <td><input type="text" id="Descripcion" name="Descripcion[]"></td> <td><input type="text" id="AplicacionesProyecto" name="AplicacionesProyecto[]"></td> <td style="width: auto"> <div class="range-field "> <input type="range" name="NivelTRL[]" min="1" value="1" max="9" /> </div> </td> </tr>'; //New input field html
var x = 1; //Initial field counter is 1
//Once add button is clicked
$(addButton).click(function() {
//Check maximum number of input fields
if (x < maxField) {
x++; //Increment field counter
$(wrapper).append(fieldHTML); //Add field html
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>
<body>
<div class="step-content">
<div class="container">
<div id="table" class="table-editable ">
<table class="table field_wrapper">
<tr>
<th>Nombre</th>
<th>DescripciĆ³n</th>
<th>Aplicaciones</th>
<th>Nivel TRL</th>
<th><i class="material-icons">add</i>
</th>
</tr>
<tr class="">
<td><input type="text" id="NombreProyecto" name="NombreProyecto[]"></td>
<td><input type="text" id="Descripcion" name="Descripcion[]"></td>
<td><input type="text" id="AplicacionesProyecto" name="AplicacionesProyecto[]"></td>
<td>
<div class="range-field">
<input type="range" name="NivelTRL[]" min="1" value="1" max="9" />
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
</body>
</html>
Everything looks perfect but when the user adds a new row and interacts with the range input, this won't feedback the user about the value he/she is picking.
Just the original one will have the tooltip.
After some testing, it even affects the 'tooltipped' class used to, well, show tooltips over any element.
This is the codepen, It's all ready to show you the problem
How to reproduce it:
In the codepen provided, you will see the blue cross, when you click on it a new row will be added.
Play around with the first range input, it will show you the value on the tooltip.
In the later added range input, it wont.
Thank you for reading, have a nice day.
You should reinit your range elements.
Simply add this code
M.Range.init($('input[type=range]'));
after this
$(wrapper).append(fieldHTML); //Add field html
First, it's not a tooltip on that range input... It's the Materialize nouiSlider effect. So you have to initialyse this on the new element.
M.Range.init(element);
By the way, I did not found this specific is the documentation about range... But I got inspired by this other initialisation example.
CodePen updated

Loop through each table row to perform math operation

I have the below jquery add table
$(document).on('click', '.add', function(){
var html = '';
html += '<tbody><tr>';
html += '<td><select name="product_name[]" class="pu-input product_name">
<option value="">--Select--</option><?php echo
fill_unit_select_box($connect); ?></select></td>';
html += '<td><input type="text" name="mt[]" class="pu-input mt" id="mt"/>
</td>';
html += '<td><input type="text" name="ream[]" class="pu-input ream"></td>';
html += '<td><input type="text" name="unit_price[]" class="pu-input
unit_price" id="price"></td>';
html += '<td><input type="text" name="d_price[]" class="pu-input d_price"
id="discount"></td>';
html += '<td><input type="text" name="td_price[]" class="pu-input td_price"
id="total_dis"></td>';
html += '<td><input type="text" name="vat[]" class="pu-input vat" id="vat">
</td>';
html += '<td><input type="text" name="t_vat[]" class="pu-input t_vat"
id="t_vat"></td>';
html += '<td><input type="text" name="total[]" class="pu-input total"
id="total"></td>';
html += '<td><button type="button" name="remove" class="btn btn-danger btn-
sm remove"><i class="fas fa-minus"></i></span></button></td></tr></tbody>';
$('#item_table').append(html);
$('tr').each(function(){
$('input').keyup(function(){ // run anytime the value changes
var mt = Number($('#mt').val()); // get value of field
var price = Number($('#price').val()); // convert it to a float
var discount = Number($('#discount').val());
var vat = Number($('#vat').val());
document.getElementById('total').value = mt * price;
document.getElementById('total_dis').value = mt * discount;
document.getElementById('t_vat').value = mt * vat;
// add them and output it
});
});
what I want to do is loop through each table row and perform a math function against two inputs, and populate the result into a third input.
but the problem is that the math functions are only working on the first row not working in the further rows.
enter image description here
As has been mentioned in the comments, HTML element ids are meant to be unique. If you are not going to assign unique ids when you create the rows (say, with a counter that you increment each time), then you are better off just omitting the element ids.
Second, there is no need to create/assign event handlers each time you add a new row. Instead, take advantage of delegated event handling. Remove your $('tr').each(function(){ entirely and instead, outside of your row adding code, put this:
$('table').on('keyup', 'input', function(){ // run anytime the value changes
$thisRow = $(this).parent().parent();console.log($thisRow.find('td>.total'));
var mt = Number($thisRow.find('td>.mt').val()); // get value of field
var price = Number($thisRow.find('td>.unit_price').val()); // convert it to a float
var discount = Number($thisRow.find('td>.d_price').val());
var vat = Number($thisRow.find('td>.vat').val());
$thisRow.find('td>.total').val(mt * price);
$thisRow.find('td>.td_price').val(mt * discount);
$thisRow.find('td>.t_vat').val(mt * vat);
// add them and output it
});
This code will traverse the DOM (admittedly probably not the most efficient thing to do) relative to the input that is currently handling the keyup event, and put values into the appropriate target inputs based on their relative locations.
DEMO
Your code is a bit obfuscated, try to format it nice next time. This will help you read it faster and will make it more maintainable.
However here is a basic example of how to achieve this:
function calculate () {
const val1 = document.getElementById('input1').value;
const val2 = document.getElementById('input2').value;
document.getElementById('output').value = Number(val1) + Number(val2);
}
$('#calculate').on('click', calculate);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="input1" type="number">
<input id="input2" type="number">
<br>
<br>
<button id="calculate">calculate</button>
<br>
<br>
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
Output <input id="output" type="number">
Once you sort out the click handler, the only real issue you have is the use of relative positioning instead of ids to locate items within the row in question. Here's your code reformatted with comments explaining the changes
$(document).on('click', '.add', function(){
var html = '';
html += '<tr>';
html += '<td><select name="product_name[]" class="pu-input product_name">
<option value="">--Select--</option><?php echo
fill_unit_select_box($connect); ?></select></td>';
html += '<td><input type="text" name="mt[]" class="pu-input mt"/>
</td>';
html += '<td><input type="text" name="ream[]" class="pu-input ream"></td>';
html += '<td><input type="text" name="unit_price[]" class="pu-input
unit_price"></td>';
html += '<td><input type="text" name="d_price[]" class="pu-input d_price"></td>';
html += '<td><input type="text" name="td_price[]" class="pu-input td_price"></td>';
html += '<td><input type="text" name="vat[]" class="pu-input vat">
</td>';
html += '<td><input type="text" name="t_vat[]" class="pu-input t_vat"></td>';
html += '<td><input type="text" name="total[]" class="pu-input total"></td>';
html += '<td><button type="button" name="remove" class="btn btn-danger btn-
sm remove"><i class="fas fa-minus"></i></span></button></td></tr>';
$('#item_table').append(html);
});
// end of add.click handler
// since #item_table exists but its rows might not yet, use a delegated event handler attached to #item_table
$('#item_table').on("keyup", "input", function() { // run anytime any value changes
// locate parent row relative to the input that was typed in
var row = $(this).closest('tr');
// locate mt and so on within the row by class - don't need id
var mt = Number(row.find('.mt').val());
var price = Number(row.find('.price').val());
var discount = Number(row.find('.discount').val());
var vat = Number(row.find('.vat').val());
// output, again find the fields by class
row.find('.total').val(mt * price);
row.find('.d_price').val(mt * discount);
// etc
});
});

How to traverse dom tree from a list of elements

I have HTML snippet which looks like this. I generate this snippet multiple times form the backend. When I click the Save button, I catch which Save button was clicked using $(this) selector. Now I want to grab the attribute item-id of the corresponding Save button. I have the following jquery code snippet. But it does not work. I have tried to look but I don't know where the error is.
<td><input type="text" size="10" value="val1" item-id="id1"></td>
<td><input type="text" value="val2" size="4"></td>
<td>
<button class="btn btn-primary save-btn">Save</i></button>
</td>
Here is the jquery snippet
$(".save-btn").click(function(){
var ems = $(this).parent().siblings();
var item_id = ems[0].child().attr("item-id");
}
click doesn't work on dynamically added elements.You need to use on('click'). Also there is no method .child() so you need to use .children().first().
This is the corrected code:
$(document).on('click', '.save-btn', function(){
var ems = $(this).parent().siblings();
var item_id = ems.children().first().attr("item-id");
});
// The text
var text="";
text += "<td><input type=\"text\" size=\"10\" value=\"val1\" item-id=\"id1\"><\/td>";
text += "<td><input type=\"text\" value=\"val2\" size=\"4\"><\/td> ";
text += "<td>";
text += " <button class=\"btn btn-primary save-btn\">Save<\/i><\/button>";
text += "<\/td>";
// Adding the text to html
$('body').html(text);
$(document).on('click', '.save-btn', function(){
var ems = $(this).parent().siblings();
console.log(ems);
var item_id = ems.children().first().attr("item-id");
alert(item_id);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
better replace item-id="id1" to data attribute html5 data-id="id1" then replace code attr('item-id') to data('id')...
$(document).on('click','.save-btn', function(){
var ems = $(this).parent().siblings(),
item_id = ems.eq(0).children('input').attr("item-id");
alert(item_id);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<td><input type="text" size="10" value="val1" item-id="id1"></td>
<td><input type="text" value="val2" size="4"></td>
<td>
<button class="btn btn-primary save-btn"><i>Save</i></button>
</td>
</tr>
</table>

jQuery remove too many fields

I am creating a form where the user can add fields one after the other. For each field I am setting a "remove" button. Each field is in a table, so I give a random id to the table, and pass this id to a removing function doing: $(random-id).remove().
The strange thing is that jQuery is removing all of the tables created by the user, as if the id is not taken into account
Why that can be?
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="http://code.jquery.com/ui/1.11.2/themes/smoothness/jquery-ui.css">
<script src="http://code.jquery.com/jquery-1.10.2.js"></script>
<script src="http://code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
<script>
function delete_field(id)
{
$("#"+id+"").remove();
}
function add_form_field()
{
id = Math.random();
html = '<table id='+id+'>\
<tr><td>Label </td></tr>\
</table>\
\
<button onclick=delete_field('+id+')>remove</button>';
$("form").append(html);
}
</script>
</head>
<body>
<form>
</form>
<button onclick=add_form_field()> Add a field </button>
</body>
</html>
Don't use Math.random, rather increment a number and create ID like: #tab_NN.
Add an ID to your Form Element id=myForm
Delegate click events to dynamically generated delete buttons using .on()
While removing the table that matched the button data-* attribute, delete the button too using .add( this ) (where this stays for the clicked button)
var id = 0;
function delete_field(event){
event.preventDefault();
$("#tab_"+ $(this).data("remove")).add(this).remove();
}
function add_form_field(){
id += 1;
var html = '<table id="tab_'+ id +'">'+
'<tr><td>Label</td></tr>'+
'</table>'+
'<button data-remove="'+id+'" class="remove">remove</button>';
$("#myForm").append(html);
}
$('#addField').on('click', add_form_field);
$('#myForm').on('click', '.remove', delete_field);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="myForm"></form>
<button id="addField"> Add a field </button>
The code above allows you to have changes in the future markup cause it targets a specific ID, but in case your DELETE buttons will always be exactly after table than you can do it without assigning ID's, by simply using .prev("table"):
http://jsbin.com/wuqati/1/edit
function delete_field(event){
event.preventDefault();
$(this).prev("table").add(this).remove();
}
function add_form_field(){
var html = '<table>'+
'<tr><td>Label</td></tr>'+
'</table>'+
'<button class="remove">remove</button>';
$("#myForm").append(html);
}
$('#addField').on('click', add_form_field);
$('#myForm').on('click', '.remove', delete_field);
Math.random() produces a floating point number less than 1 which is invalid for an id. You can use a global variable to keep count of the rows created. Keep in mind that a CSS ID can not start with a digit. So append the number to a string before using it as an ID.
<script>
function delete_field(id)
{
$("#"+id+"").remove();
}
tableID = 1;
function add_form_field()
{
id = 'table-'+tableID;
html = '<table id='+id+'>\
<tr><td>Label </td></tr>\
</table>\
\
<button onclick=delete_field('+id+')>remove</button>';
$("form").append(html);
tableID++;
}
</script>
Why not simplify this by doing something like below.
$(".remover").click(function() {
$(this).parent().remove();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<td>
<input type="text" placeholder="input One"/> <input type="button" class="remover" value="remove" />
</td> </tr>
<tr>
<td>
<input type="text" placeholder="input Two"/> <input type="button" class="remover" value="remove" />
</td> </tr>
<tr>
<td>
<input type="text" placeholder="input Three"/> <input type="button" class="remover" value="remove" />
</td> </tr>
</table>

JavaScript calendar not working when adding a div

I have a JS calendar script that works fine in one div. I also have a jQuery script that takes the div and clones it. The calendar script does not work in the cloned div, though. The calendar does not pop up. Here is my code:
<script type="text/javascript" src="tcal.js"></script>
<script>
$(document).ready(function () {
$('#addRow').click(function () {
$('<div/>', {
'class': 'extraPerson',
html: GetHtml()
}).hide().appendTo('#container1').slideDown('slow');
});
function GetHtml() {
var len = $('.extraPerson').length;
var $html = $('.extraPersonTemplate').clone();
$html.find('[name=puloc]')[0].name = "puloc" + len;
$html.find('[name=pudate]')[0].name = "pudate" + len;
$html.find('[name=putime]')[0].name = "putime" + len;
$html.find('[name=punumber]')[0].name = "punumber" + len;
return $html.html();
}
});
</script>
<div class="extraPersonTemplate">
<table frame="box" style="width:500px">
<tr>
<td colspan="3">
<?php
//php code to access mysql database
echo '<select name="puloc" style="width: 482px">';
echo '<option value="">--Select Origin Location--</option>';
while($opt = mysql_fetch_array($resultOptions))
{
echo '<option value="'.$opt['displayName'].'">'.$opt['displayName'].'</option>';
}
echo '</select>';
?>
</td>
</tr>
<tr>
<td>
<link rel="stylesheet" type="text/css" href="tcal.css" />
<script type="text/javascript" src="tcal.js"></script>
Pick up date:<BR>
<input class="tcal" placeholder="" type ="text" name="pudate" style="width:130px">
</td>
<td>
Pick up time<br>
<input placeholder="" type ="text" name="putime" style="width:150px">
</td>
<td>
Pick up number<BR>
<input placeholder="" type ="text" name="punumber" style="width:150px">
</td>
</tr>
</table>
<div></div>
</div>
<div id="container1">
<script type="text/javascript" src="tcal.js"></script>
</div>
<i class="icon-plus-sign icon-white"></i> Add Origin</p>
Here is my javascript file on pastebin: http://pastebin.com/WEhJHUKe
The tCal code only runs once, when you generate the page (see the very final method in the js class, which adds an event handler for window.onload). It looks at the page at that time and adds the tCal element to the row it sees with the class 'tcal'. Adding another row (even with that class) will not trigger another update.
When you add another row, try running f_tCalInit() again--this should force it to inspect the page again, find your new row with the 'tcal' class, and append the date control to it.
Put the code that binds the calendar into a function, and after cloning and adding a new field to page, call the function again to bind the calendar again

Categories