jquery and console.log issue - javascript

I have multiple toggle switches on my page. They are from bootstrap.
Everything works as expected, however, I have come across an error within the javascript console. Or warning should I say.
When I have only one toggle on the page and I click it it will print one line in the console, which is as expected. When I dynamically add another toggle, using the script below, when I click on the last added toggle it will print again only one line, but every other will print multiple lines.
I.e. when I have 5 toggles and click on the last one, it will print one line in the console.
When I click on 4th it will print two lines and so on. When I click on the 1st it will print 5 lines.
If I have multiple toggles set from beginning without adding them dynamically it works fine.
Any ideas?
<script>
$(window).ready(function() {
$("[data-toggle='toggle']").bootstrapToggle({
on: 'On',
off: 'Off',
size: 'small'
});
$('#addRow').on('click', function(event) {
event.preventDefault();
var rowID =+ $('table tr:last').attr('id')+1;
$('#users').find('tbody').append([
"<tr class='userRow' id='"+rowID+"'>",
"<td>"+rowID+"</td>",
"<td><input type='text' class='form-control'></td>",
"<td><input type='text' class='form-control'></td>",
"<td><input type='text' class='form-control'></td>",
"<td><input type='checkbox' class='toggle-voicemail' data-toggle='toggle'></td>",
"<td><input type='checkbox' data-toggle='toggle' class='toggle-ringgroup'></td>",
"<td><input type='checkbox' data-toggle='toggle' class='toggle-ringgroup'></td>",
"<td><input type='checkbox' data-toggle='toggle' class='toggle-ringgroup'></td>",
"<td><a class='deleteRow btn btn-danger' value='"+rowID+"'>Delete</a></td>",
"</tr>"
].join(''));
$("[data-toggle='toggle']").bootstrapToggle('destroy');
$("[data-toggle='toggle']").bootstrapToggle({ size: 'small' });
$('.toggle-voicemail').on('change', function(event) {
event.preventDefault();
var id = $(this).parents('tr').attr('id');
console.log("Voicemail for userID:"+id);
});
});
$('.toggle-voicemail').on('change', function(event) {
event.preventDefault();
var id = $(this).parents('tr').attr('id');
console.log("Voicemail for userID:"+id);
});
$('#users').on('click', 'a.deleteRow', function(event) {
event.preventDefault();
//var id = $(this).find('a').attr('value');
$(this).parents('tr').remove();
});
});
</script>
HTML
<div class="box box-primary" id="usersDetails" style="">
<div class="box-header with-border">
<h3 class="box-title">Users</h3>
</div>
<div class="box-body">
<table class="table table-condensed text-center" id="users">
<thead>
<tr>
<th>ID</th>
<th width="300">Username</th>
<th>Phone</th>
<th></th>
<th>Voicemail</th>
<th width="50">RG 1</th>
<th width="50">RG 2</th>
<th width="50">RG 3</th>
<th width="100"></th>
</tr>
</thead>
<tbody>
<tr class='userRow' id='1'>
<td>1</td>
<td><input type='text' class='form-control'></td>
<td><input type='text' class='form-control'></td>
<td><input type='text' class='form-control'></td>
<td><input type='checkbox' class='toggle-voicemail' data-toggle='toggle'></td>
<td><input type='checkbox' data-toggle='toggle' class='toggle-ringgroup'></td>
<td><input type='checkbox' data-toggle='toggle' class='toggle-ringgroup'></td>
<td><input type='checkbox' data-toggle='toggle' class='toggle-ringgroup'></td>
<td></td>
</tr>
</tbody>
</table>
<input type="button" id="addRow" value="Add another user" class="btn btn-success">
</div>
</div>

You're binding this event inside of your "add row" functionality:
$('.toggle-voicemail').on('change', function(event) {
Which means every time you add a row, you're adding another binding to every matching .toggle-voicemail element on the page, including the ones which already have that event binding.
Instead of re-binding when adding a row, create a delegated binding once when the page loads that handles dynamically added elements. Basically, do this outside of the "add row" functionality:
$(document).on('change', '.toggle-voicemail', function(event) {
event.preventDefault();
var id = $(this).parents('tr').attr('id');
console.log("Voicemail for userID:"+id);
});

You are adding the event function multiple times. The solution to this is to make your function non-anonymous:
var myFunc = function(event) {
event.preventDefault();
//var id = $(this).find('a').attr('value');
$(this).parents('tr').remove();
}
And then call .off to before calling .on to prevent multiple listeners
$('.toggle-voicemail').off('change', myFunc);
$('.toggle-voicemail').on('change', myFunc);

That is caused because every time you add a new toggle, you reattach the event listener to all of the existing toggles and not only for the newly created one.
You can make a let variable to store the newly generated toggle, and then instead of doing
$('.toggle-voicemail').on('change', function(event) { ...
you can do:
$elem.on('change', function(event) { ...

It looks like your problem is that you are just adding event handlers and never removing them. So you need to only add an event handler to the newly-added element, or remove all event handlers (using .off()) ,and then adding them again.
I would opt for the former approach (adding an event listener to the new element only).
The best way to do this is the create the elements, then add all your event handlers (and whatever else you want to change about the element). THEN append it to the DOM.
so:
// create the new row.
// reusing your `.join()` technique for ease of demo here.
var newRow = $("<tr class='userRow' id='"+rowID+"'>",
"<td>"+rowID+"</td>",
"<td><input type='text' class='form-control'></td>",
"<td><input type='text' class='form-control'></td>",
"<td><input type='text' class='form-control'></td>",
"<td><input type='checkbox' class='toggle-voicemail' data-toggle='toggle'></td>",
"<td><input type='checkbox' data-toggle='toggle' class='toggle-ringgroup'></td>",
"<td><input type='checkbox' data-toggle='toggle' class='toggle-ringgroup'></td>",
"<td><input type='checkbox' data-toggle='toggle' class='toggle-ringgroup'></td>",
"<td><a class='deleteRow btn btn-danger' value='"+rowID+"'>Delete</a></td>",
"</tr>".join(''));
// toggle-ify the element.
newRow.find("[data-toggle='toggle']").bootstrapToggle({ size: 'small' });
newRow.find('.toggle-voicemail').on('change', function(event) {
event.preventDefault();
var id = $(this).parents('tr').attr('id');
console.log("Voicemail for userID:"+id);
});
newRow.find('a.deleteRow').on('click', function(event) {
event.preventDefault();
//var id = $(this).find('a').attr('value');
$(this).parents('tr').remove();
});
// append to table.
$('#users').find('tbody').append(newRow);

Related

jQuery get value closest input field

I have HTML code like this:
<tr>
<td class='qty'><input class='narrow' value='1' /><i class='fa fa-trash' aria-hidden='true'></i></td>
<td class='comm'><input class='narrow' value='' size='5'/></td>
</tr>
This code will be auto generated by a JS function, so it happens more often.
to get the Value from the first input I use this function:
jQuery('#tbl_order .qty input').bind('change', function() {
Within this function I want to get the next input value. I have tried this what does not work
jQuery(this).closest(".comm input").val()
.closest()
For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
You can use find() on the closest tr element. I will also prefer using on() and input event instead of bind() and change respectively.
Demo:
jQuery('#tbl_order .qty input').on('input', function() {
var nextVal = jQuery(this).closest("tr").find(".comm input").val();
console.log(nextVal);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr id="tbl_order">
<td class='qty'><input class='narrow' value='1' /><i class='fa fa-trash' aria-hidden='true'></i></td>
<td class='comm'><input class='narrow' value='1234' size='5'/></td>
</tr>
</table>
You can use next() combines with closest()
$('#tbl_order .qty input').bind('change', function() {
var $currentTd = $(this).closest("td");
var $nextTd = $currentTd.next();
var value = $nextTd.find("input").val();
console.log(value);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="tbl_order">
<tr>
<td class='qty'><input class='narrow' value='1' /><i class='fa fa-trash' aria-hidden='true'></i></td>
<td class='comm'><input class='narrow' value='' size='5'/></td>
</tr>
</table>
$('.fa fa-trash').on('click', function () {
$tr = $(this).closest('tr');
var data = $tr.children('td').map(function () {
return $(this).text();
}).get();
console.log(data);
<table id="tbl_order">
<tr>
<td><input class='narrow' value='1' /><i class='fa fa-trash' aria-
hidden='true'></i></td>
<td><input class='narrow' value='' size='5'/></td>
</tr>
</table>
this may give you some idea about mapping function. here I give jquery onclick class to fa fa-trash. so whenever the event is fired the particular row get selected. (i hope in the table your getting data from backend code)

Trying to Add Row dynamically but getting error

I'm trying to add row consist of three textbox dynamically on click of button with id=btnASize and on click of button with id=btnASizeR want to add a row consist of four textboxes. and on click of button with id=btnWdDelete want to delete the last row which is generated with textboxes and so on.
The three buttons which is mentioned above are generated dynamically and rows with textboxes which will be generated below existing rows are also created on click of those dynamic buttons.Any idea would be appreciated Refer image
$("#btnASize").click(function () {
AddRow($("#SizeR").val(), $("#TolMin").val(), $("#TolMax").val());
$("#SizeR").val("");
$("#TolMin").val("");
$("#TolMax").val("");
});
function insertRow(){}
function AddRow(SizeRange, Tolerancemin,Tolerancemax) {
//Get the reference of the Table's thead element.
var tBody = $("#WireDimTbl > thead> tr")[0];
//Add Row.
row = tBody.insertRow(-1);
//Add Size cell.
var cell = $(row.insertCell(-1));
cell.html(SizeR);
//Add TolMin cell.
cell = $(row.insertCell(-1));
cell.html(TolMin);
//Add TolMax cell.
cell = $(row.insertCell(-1));
cell.html(TolMax);
}
$("#btnWdDelete").click(function () {
var row = $("#SizeR").closest("tr");
//Get the reference of the Table.
var table = $("#WireDimTbl")[1];
//Delete the Table row using it's Index.
table.deleteRow(row[1].rowIndex);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<tr>
<td class='text-left'><strong>Standard Sizes & Tolerances</strong></td>
<td>
<input type='button' ID='btnASize' value='AddSize' />
<input type='button' ID='btnASizeR' value='AddSizeRange' />
<input type='button' ID='btnWdDelete' value='Delete' />
<table ID='WireDimTbl' class='table table-bordered'>
<thead>
<tr>
<th class='text-center'>Size Range (mm)</th>
<th class='text-center'>Tolerance (-)mm</th>
<th class='text-center'>Tolerance (+) mm</th>
</tr>
</thead>
<tr>
<td class='text-center'>
<input type='text' ID='SizeR' value='2.00' />
</td>
<td>
<input type='text' ID='TolMin' value='1' />
</td>
<td>
<input type='text' ID='TolMax' value='1' />
</td>
</tr>
</table>
</td>
</tr>
I prepared this sample to fulfill your requirement, although not a complete solution. You have to write some code by yourself. But this will give you a pretty good idea.
$('#btnAdd').click(function() {
var textboxSize = "<input class='form-control' type='text' class='size range'>";
var textboxTolerance = "<input class='form-control' type='text' class='tolerance'>";
var markup = "<tr><td>" + textboxSize + "</td><td>" + textboxTolerance + "</td></tr>";
$("#myTable tbody").append(markup);
});
$('#btnDelete').click(function() {
$("#myTable tbody>tr:last").remove();
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" />
<input class="btn-primary" id="btnAdd" type="button" value="Add Row">
<input class="btn-primary" id="btnDelete" type="button" value="Delete">
<table class="table" id="myTable">
<thead>
<th>
Size Range
</th>
<th>
Tolerance
</th>
</thead>
<tbody>
</tbody>
</table>
I think there are a few issues with your code.
You call insertRow on an HTMLTableRowElement. insertRow is a HTMLTableElement method, so we need to make sure we're calling it on a HTMLTableElement, instead of a HTMLTableRowElement. To fix this, we'll select the table. We can then use insertRow() on it.
You call $(row.insertCell(-1)) to insert a cell. This is invalid jQuery code. insertCell is a plain JS method for a HTMLTableRowElements, so we need to make sure we're calling it on the appropriate type of element. Specifically, we'll use row.insertCell(), instead of $(row.insertCell(-1)).
The Delete function contains similar errors, but I'll leave that one as is so you can learn by correcting it yourself.
$("#btnASize").click(function() {
AddRow($("#SizeR").val(), $("#TolMin").val(), $("#TolMax").val());
$("#SizeR").val("");
$("#TolMin").val("");
$("#TolMax").val("");
});
function AddRow(SizeRange, Tolerancemin, Tolerancemax) {
//Get the reference of the Table's thead element.
var tBody = $("#WireDimTbl")[0];
//Add Row.
row = tBody.insertRow(-1);
//Add Size cell.
var cell1 = row.insertCell(-1);
$(cell1).text(SizeRange);
//Add TolMin cell.
var cell2 = row.insertCell(-1);
$(cell2).text(Tolerancemin);
//Add TolMax cell.
var cell3 = row.insertCell(-1);
$(cell3).text(Tolerancemax);
}
$("#btnWdDelete").click(function() {
var row = $("#SizeR").closest("tr");
//Get the reference of the Table.
var table = $("#WireDimTbl")[1];
//Delete the Table row using it's Index.
table.deleteRow(row[1].rowIndex);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<tr>
<td class='text-left'><strong>Standard Sizes & Tolerances</strong></td>
<td><input type='button' ID='btnASize' value='AddSize' /><input type='button' ID='btnASizeR' value='AddSizeRange' /><input type='button' ID='btnWdDelete' value='Delete' />
<table id='WireDimTbl' class='table table-bordered'>
<thead>
<tr>
<th class='text-center'>Size Range (mm)</th>
<th class='text-center'>Tolerance (-)mm</th>
<th class='text-center'>Tolerance (+) mm</th>
</tr>
</thead>
<tr>
<td class='text-center'><input type='text' ID='SizeR' value='2.00' /></td>
<td><input type='text' ID='TolMin' value='1' /></td>
<td><input type='text' ID='TolMax' value='1' /></td>
</tr>
</table>
</td>
</tr>

Delete a table row on button click in Javascript

I have a table with the following 3 columns where each row is dynamically appended.
Condition : Is a mere WHERE clause conditional statement string
Remove : A button that removes that row (Removes a condition)
Join with : A drop down combo
When the user clicks on the Remove button, that particular row needs to be removed.
I have written the code for this, but nothing happens and am not getting any errors on the console as well.
Code in Context
$("#whereConditionTable").append(
"<tr>"+
"<td>"+conditionString+"</td>"+
"<td><button id='removeConditionBtn' name='removeConditionBtn' class='btn btn-default'><img src='resources/images/removeWhereCondition.png' width='25px' height='25px'></button>"+
"<td>"+
"<select id='where-Condition-Join-Combo' name='where-Condition-Join-Combo' class='form-control'>"+
"<option value='1'>Join using</option>"+
"<option value='2'>AND</option>"+
"<option value='3'>OR</option>"+
"</select>"+
"</td>"+
"</tr>"
);
document.getElementById("removeConditionBtn").addEventListener("click", function() {
removeWhereCondition();
}, false);
removeWhereCondition()
function removeWhereCondition()
{
$(this).closest("tr").remove();
}
Any suggestions in this regard will be highly appreciated.
function deleteRow(r) {
var i = r.parentNode.parentNode.rowIndex;
document.getElementById("myTable").deleteRow(i);
}
<!DOCTYPE html>
<html>
<head>
<style>
table, td {
border: 1px solid black;
}
</style>
</head>
<body>
<table id="myTable">
<tr>
<td>Row 1</td>
<td><input type="button" value="Delete" onclick="deleteRow(this)"></td>
</tr>
<tr>
<td>Row 2</td>
<td><input type="button" value="Delete" onclick="deleteRow(this)"></td>
</tr>
<tr>
<td>Row 3</td>
<td><input type="button" value="Delete" onclick="deleteRow(this)"></td>
</tr>
</table>
</body>
</html>
Few things to fix:
You're combining jQuery and vanilla JavaScript (getElementById), so I've tidied some of that up and rewritten it as jQuery.
HTML documents can not have repeating IDs. If your append ran more than once, it would create additional #removeConditionBtn and #where-Condition-Join-Combo elements, and JS would cease to work. I've changed these to classes, which are reusable.
Your addEventListener to bind a click event was only going to bind to (one) #removeConditionBtn element that existed when the code was first run. If the table contents changed to include additional buttons, your binding wouldn't have updated (even if you were using class rather than ID). I've rewritten this using jQuery on on the table itself, so the click event will still fire even as the contents of the table change.
Working demonstration below:
var conditionString = "text";
$("#whereConditionTable").append(
"<tr>" +
"<td>" + conditionString + "</td>" +
"<td><button class='removeConditionBtn' name='removeConditionBtn' class='btn btn-default'><img src='resources/images/removeWhereCondition.png' alt='Remove' width='25px' height='25px'></button>" +
"<td>" +
"<select class='where-Condition-Join-Combo' name='where-Condition-Join-Combo' class='form-control'>" +
"<option value='1'>Join using</option>" +
"<option value='2'>AND</option>" +
"<option value='3'>OR</option>" +
"</select>" +
"</td>" +
"</tr>"
);
$("#whereConditionTable").on("click", ".removeConditionBtn", function() {
$(this).closest("tr").remove();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="whereConditionTable"></table>
Apparently you are using jQuery. You could try:
$('#removeConditionButton').on('click', function(element) {
$(element).closest('tr').remove();
})
By the way, it seem you are using id-property incorrectly. Id's should be unique and each page can have only one element with same id. In this case, you should use class instead of id.

Get total from table input as grand total in jquery?

I created a simple stock saving table for my project. Also i added a button to add row to my table.this is my table,
[add button]
+---------------+-----------+-----------+
+ lense type + qty + total +
+---------------+-----------+-----------+
+ + + +
+---------------+-----------+-----------+
+ grand total : LKR +
+---------------------------------------+
EDIT
I added html code of the table,
<table class="table" id="tbl-add-lense">
<thead style="background-color:#f5edff;">
<th style="width:2%;"><input type="checkbox" name="chk_in" id="checkall"></input></th>
<th style="width:2%;">item no</th>
<th style="width:5%;">Lense Type</th>
<th style="width:5%;">Unit price</th>
<th style="width:5%;">Quantity</th>
<th style="width:5%;">Total</th>
</thead>
<tbody id="tbl-lesne-body">
<tr id="addr0">
<td><input type="checkbox" name="chk_in"></input></td>
<td>1</td> <td><input name='tb-lense-type1' type='text' placeholder='Lense Type' class='form-control '/> </td>
<td><input name='td-lunit1' type='number' placeholder='0' class='form-control'></td>
<td><input name='td-lqty1' type='number' placeholder='0' class='form-control'></td>
<td><input name='tb-ltotal1' type='number' placeholder='00.00' class='form-control total'></td>
</tr>
</tbody>
<tfooter></tfooter>
</table>
This table has one row. I used add button to add more rows. add row button code,
$("#add-lense-row").click(function(){
$("#tbl-lesne-body").append("<tr id='addr"+(i+1)+"'><td><input type='checkbox' name='chk_in'></input></td><td>"+ (i+1) +"</td> <td><input name='tb-lense-type"+i+"' type='text' placeholder='Lense Type' class='form-control '/> </td> <td><input name='td-lunit"+i+"' type='number' placeholder='0' class='form-control'></td><td><input name='td-lqty"+i+"' type='number' placeholder='0' class='form-control'></td><td class='tot'><input name='td-ltotal"+i+"' type='number' placeholder='00.00' class='form-control total'></td></tr>");
i++;
});
total <td> has a input ,
<input name='tb-ltotal1' type='number' placeholder='00.00' class='form-control total'>
I need to get sum of total td inputs when typing on a input. I tried this code,
$(".total").keyup(function(){
console.log('Typing');
sum += parseFloat($(this).val());
});
but it only working on the first table row. If i add a new row and try this code. It's not working. I removed sum += parseFloat($(this).val()); line and tried. Still code working only in the first row. How to solve this. Thank you
Your code needed some corrections:
You were only getting the value of input that triggered the 'keyup' event, as the sum. But you needed to loop through all inputs with class total and add the values of all to get the grand total.
As only the first row was added through html and rest of the rows were being added dynamically through javascript/jquery, your normal event binding worked only for the first row. For dynamically generated elements i.e. the elements which were not there when the page first loaded, you need to use slightly different syntax for event binding e.g. $(document).on("keyup", ".total", function(){}). By binding events dynamically in this way, keyup event now fires on all inputs.
$(document).on("keyup", ".total", function(){
console.log('Typing');
var sum = 0;
$(".total").each(function(index){
sum += parseFloat($(this).val());
});//each
console.log( sum );
});//keyup`

How to assign an incremental id while appending rows in table?

Just need your help.
My problem is I am creating a dynamic form. In my form there is a button and below that is a table.
The scenario is:
1. The user will click the the button
2. After clicking the button the table row will dynamically added. Inside my row there is a textbox
I can do that but how can i do the process after the user click the button. The row will append together with a textbox. But I want to assign a unique ID in a textbox. In my case I want to do this incremental.
Here's my js:
$(document).ready(function(){
$("[data-item]").on('click',function(){
$("#grid1 tbody").append("<tr><td><input type='text' value='123' style='width:100px' id='' /></td></tr>");
});
});
Here's my table:
<input type="button" name="add" data-item="123" value="ADD" class="test" id="test" />
<table id="grid1" border="1" style="width: 40%">
<thead>
<tr>
<th style="text-align: center;">CODE</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
Here's the fiddle:
http://jsfiddle.net/rochellecanale/xvdMz/
keep a counter
$(document).ready(function(){
var counter = 0;
$("[data-item]").on('click',function(){
$("#grid1 tbody").append("<tr><td><input type='text' value='123' style='width:100px' id='in-" + counter++ + "' /></td></tr>");
});
});
Demo: Fiddle
You can do it this way:
When you create a new row you can check for the current input's length and add that as a part of id.
$("[data-item]").on('click',function(){
var $el = $("<tr><td><input type='text' id='myInput" + ($('#grid1').find('input').length +1) + "' value='123' style='width:100px' id='' /></td></tr>");
$("#grid1 tbody").append($el);
});
Demo
I have another suggestion that instead of keeping the items to be cloned, you can go for templating, least you can put in your html itself like this.
<script type="text/html" id="clone">
<tr><td><input type='text' value='123' style='width:100px' id='' /></td></tr>
</script>
and then just use that to clone, this way you keep your html in one place and script in another.
$("[data-item]").on('click',function(){
var $el =$($.parseHTML($('#clone').html())).find('input').prop('id', "myInput" + ($('#grid1').find('input').length +1) ).end();
$("#grid1 tbody").append($el);
});
Demo

Categories

Resources