This question already has answers here:
Click event doesn't work on dynamically generated elements [duplicate]
(20 answers)
Closed 2 years ago.
I have a html table like so -
<table class="table" id="myTable">
<thead>
<th>Email</th>
<th>Delete</th>
</thead>
<tbody>
</tbody>
I can dynamically add to the table doing this:
var tbody = $('#myTable').children('tbody');
var table = tbody.length ? tbody : $('#myTable');
table.append("<tr><td>"+user_email+"</td><td><input type='button' value='Del' id ='"+user_id+"'class='btn btn-danger btn-sm'></td></tr>");
But when I try to remove a row doing this:
$('input[type="button"]').click(function(e){
$(this).closest('tr').remove()
})
The row don't remove. How do I resolve this?
You were pretty close, since the TR and the button are dynamically generated,
use the .on() method:
$("#myTable").on("click", "input[type='button']", function(e){
$(this).closest('tr').remove()
});
Sometimes not using jQuery may help you understand what's actually happening. Here's a snippet that may be helpful.
// add the listener to the document (event delegation)
document.addEventListener("click", deleteRow);
// add a first row
addRow(document.querySelector("#myTable"));
function deleteRow(evt) {
// read data-property (data-delete or data-add)
if (evt.target.dataset.delete) {
// retrieve the row to delete
const row2Delete = evt.target.closest("tr");
// remove that from *its parent* (the table)
row2Delete.parentNode.removeChild(row2Delete);
} else if (evt.target.dataset.add) {
addRow(document.querySelector("#myTable"));
}
return true;
}
function addRow(toTable) {
// create a row
const row = document.createElement("tr");
// create 2 cells
const cell1 = document.createElement("td");
const cell2 = cell1.cloneNode(true);
//create a button for the second cell
const bttn = document.createElement("button");
bttn.dataset.delete = "1";
bttn.textContent = "delete";
// fill the first cell with a random e-mailaddress
cell1.appendChild(document.createTextNode(`someUser${
Math.floor(1 + Math.random() * 10000000)}#somewhere.net`));
// append button to cell2
cell2.appendChild(bttn);
// append cells to row
row.appendChild(cell1);
row.appendChild(cell2);
// append row to table
toTable.appendChild(row);
}
<button data-add="1">Add a row</button>
<table class="table" id="myTable">
<thead>
<th>Email</th>
<th>Delete</th>
</thead>
<tbody>
</tbody>
Related
so im trying to add a buttons to the end of each row since the table is dynamic I have to use javascript to append it but everytime I try it doesn't work if it does it will just put a button at the end of the last row of the table. Heres an image of what I get linked below
enter image description here
<!--TABLE HEADER SECTION-->
<div class="div0">
<table class="tableHeader">
<thead>
<tr>
<th>Store</th>
<th>Product</th>
<th>Profile</th>
<th>Proxies</th>
<th>Status</th>
<th>ACTION</th>
</tr>
</thead>
</table>
</div>
<!--TABLE SECTION-->
<div class="div1">
<table id = "botTasksTable" class="table table-dark table-sm table-bordered">
<tbody>
<tr>
<td>another name</td>
<td>mockdata</td>
<td>mockdata</td>
<td>mockdata</td>
<td>mockdata</td>
</tr>
</tbody>
</table>
</div>
<script type="text/javascript">
const tableBody = document.querySelector("#botTasksTable > tbody");
//function to load table into tbody from jsonfile bottable which would be the users given tasks
function loadBotTasksTable() {
const request = new XMLHttpRequest();
request.open("get", "data/botTable.json"); //grabs the data from the json file its in the data file/ and named bottable.json
request.onload = () => {
const json = JSON.parse(request.responseText); //attempts to parse the data it gets
populateTable(json);
};
request.send(); //sends out the request for thr function
}
var btn = document.createElement("BUTTON");
var btn = document.createElement("BUTTON"); // Create a <button> element
btn.innerHTML = "CLICK ME"; // Insert text
function populateTable(json) {
//this while loop clears out existing table data!
//we want to add this back but adding a value to first child even if its a mock value.
while (tableBody.firstChild) { //so basically checking if the table has <tr> <td></td> </tr> so a row and column
tableBody.removeChild(tableBody.firstChild)
}
//now we populate table
json.forEach((row) => { //loops through each row [ SUPREME, Nike SB Dunks, profile1, proxy22, In Progress ]
const tr = document.createElement("tr"); //create the new row
row.forEach((cell) => { //loops through each individual column of the row EX : SUPREME
const td = document.createElement("td");
td.textContent = cell // passes whatever data the json file had in the cell into the text content of the row
tr.appendChild(td);
});
//for each cell in the row get the index and append
tableBody.appendChild(tr); //appends the row into the table body row by row as i runs through the for loop
});
loopTable();
}
//loop through table and add button to the table
function loopTable() {
var table = document.getElementById('botTasksTable');
for (var i = 0, row; row = table.rows[i]; i++) {
//iterate through rows
//rows would be accessed using the "row" variable assigned in the for loop
row.appendChild(btn);
console.log(i);
}
};
You need to create a new button for each row, and put it inside a <td>. You can use cloneNode() to make a copy of an element.
//loop through table and add button to the table
function loopTable() {
var table = document.getElementById('botTasksTable');
for (var i = 0, row; row = table.rows[i]; i++) {
let td = document.createElement('td');
td.appendChild(btn.cloneNode());
row.appendChild(td);
console.log(i);
}
};
I Created a HTML Table and Created 1 Row in it... I created two functions first to Clone and the Row and second to Remove the Row..
using appendchild and removechild function
But removeChild Function Deletes the Main Row as well...
I want the removeChild Function to be only able to remove cloned Rows, Not the original row...
Note: in Clone of Row, I have replaced the ID with " ". to remove duplicate id.
i Tried to do this by creating a if statement which check if the id of row is same as original row only then remove the row. but I think I am not doing it in right way.. Below is code..
<table id="table-logic">
<tbody id="qualiBody">
<tr>
<td>column 1</td>
<td>column 2</td>
<td>column 3</td>
<td>column 4</td>
</tr>
</tbody>
</table>
<a onclick="cloneRow()">Add Row</a><br>
<a onclick="removeRow()">Remove Row</a>
//clone Row with changed id
function cloneRow() {
var row = document.getElementById('addr00'); // find row to copy
var table = document.getElementById("qualiBody"); // find table body to append to
var clone = row.cloneNode(true); // copy children too
clone.id = ' '; // change id to a blank space
table.appendChild(clone) // add new row to end of table
}
//Remove Row
function removeRow() {
var table = document.getElementById("qualiBody"); // find table to append to
var mainRow = document.getElementById("qualiBody")
if (mainRow.childNodes.id != 'addr00') {
table.removeChild(qualiBody.lastChild);
}
}
I expect to make my removeRow Function only remove cloned Rows... Not the Original Row...
I think the if statement can work in that part by Just making javascript check the id of element... if id of row != id of original row .. remove last child.
//clone Row with changed id
function cloneRow() {
var row = document.getElementById('addr00'); // find row to copy
var table = document.getElementById("qualiBody"); // find table body to append to
var clone = row.cloneNode(true); // copy children too
clone.classList.add("cloned");
table.appendChild(clone) // add new row to end of table
}
//Remove Row
function removeRow()
{
var table = document.getElementById("qualiBody");
let last = table.lastElementChild;
if (last.classList.contains("cloned"))
{
last.remove();
}
}
<table id="table-logic">
<tbody id="qualiBody">
<tr id="addr00"><td>column 1</td><td>column 2</td><td>column 3</td><td>column 4</td></tr>
<tr class="cloned"><td>column 1</td><td>column 2</td><td>column 3</td><td>column 4</td></tr>
<tr class="cloned"><td>column 1</td><td>column 2</td><td>column 3</td><td>column 4</td></tr>
<tr class="cloned"><td>column 1</td><td>column 2</td><td>column 3</td><td>column 4</td></tr>
</tbody>
</table>
<a onclick="cloneRow()">Add Row</a><br>
<a onclick="removeRow()">Remove Row</a>
So I am having trouble deleting all of the data in an HTML table with js WITHOUT deleting the header. Here is my HTML:
<html>
<title>Z80 Opcodes</title>
<body>
<input type="text" id = "input" value = "">
<button onClick = "hex()">Hex</button>
<button onClick = "bin()">Bin</button>
<button onClick = "assem()">Assembly</button>
<button onClick = "find()">Find</button>
<table id = "out" style="width:100%">
<thead>
<th align="left">Binary</th>
<th align="left">Hex</th>
<th align="left">Assembly</th>
<th align="left">Description</th>
</thead>
<tbody id="tb">
</tbody>
<script src = "js/script.js">
</script>
</body>
</html>
And here is script.js:
var id = document.getElementById("out");
var ab = "";
var row;
var table = ['0000000000nopno operation', '0000000101ld (bc), **loads ** into BC'];
var bin = ['00000000', '00000001'];
var hex = ['00', '01'];
var assembly = ['nop', 'ld (bc), **'];
var description = ['no operation', 'loads ** into BC'];
l = table.length;
function find() {
row = id.insertRow(0);
for (i=0;i <=l-1;i++) {
ab = table[i];
if (ab.includes(document.getElementById("input").value)) {
row = id.insertRow(-1);
cell1 = row.insertCell(0);
cell2 = row.insertCell(1);
cell3 = row.insertCell(2);
cell4 = row.insertCell(3);
cell1.innerHTML = bin[i];
cell2.innerHTML = hex[i];
cell3.innerHTML = assembly[i];
cell4.innerHTML = description[i];
}
}
}
I have omitted A LOT of array entries because they contained almost the FULL instruction set of thee z80 microprocessor.
What this code does (basically) is it gets an input from the user and if the array table contains that input then it gets the corresponding values from bin, hex, assembly and description and assigns each a column in the table out, then adds a row with the for the data. However, I cannot seem to find a way to delete all of the rows in tbody before another set of values are appended to the table without deleting thead. I have searched around on the web and found several solutions, none of which worked. They either deleted the thead or caused some kind of error (I'll give examples if you ask). I am using Google Chrome version 63.0.3239.132 web browser to run my code.
As you may be able to see I am quite new to js and HTML
Any ideas what I have done wrong?
~Jachdich
First You have to close your <table> tag </table>
This is how you can clear your table.
$('#remove').on('click', ()=>{
$('#tb').empty()
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id = "out" style="width:100%">
<thead>
<th align="left">Binary</th>
<th align="left">Hex</th>
<th align="left">Assembly</th>
<th align="left">Description</th>
</thead>
<tbody id="tb">
<tr>
<th>01010101</th>
<th>1231:sdf:sdf42</th>
<th>213123</th>
<th>description</th>
</tr>
</tbody>
</table>
<button id="remove">
clear
</button>
Assuming you want to keep the tbody element intact instead of just removing it and all its children at once:
// get a reference to the tbody element
var tb = document.querySelector('#out tbody');
// while tb has children, remove the first one
while (tb.childNodes.length) {
tb.removeChild(tb.childNodes[0]);
}
// tb is now empty
From a semantic perspective, it would make the removal of rows much easier if you added them to the <tbody> element instead of the <thead> element. This way, you could target the rows within the body and remove them whilst preserving your <thead> (sibling node to ):
var body = document.querySelector('tbody');
while (body.firstChild) {
// This will remove all children within tbody which in your case are <tr> elements
body.removeChild(body.firstChild);
}
body.removeChild(rowsWithinBody)
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tbody#examples
with jQuery you can do it simply in a single line of code.
$("#table_id tbody tr").remove();
it will remove all rows in a table except the header.
I'm using bootstrap-table where one of the columns is a drop-down menu:
<table data-toggle="table" id="table" data-unique-id="id">
<thead>
<tr>
<th data-field="type">type</th>
<th data-field="id">id</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
However, when appending a new row using:
$('#table').bootstrapTable('append', {
id: newId,
type: '<select name="type" class="select-type"><option value="foo">foo</option><option value="bar">bar</option></select>'
})
The option selected in previous rows isn't saved.
Demo
Update: The method in my answer works well for small tables, but using it in tables of 100+ rows is awfully slow, so I'm still looking for a solution.
I've added an event listener that uses bootstrap-table's api to update values after the option is selected.
$('#table').on('change', '.select-type', function(eventt) {
const elem = eventt.target;
elem[elem.selectedIndex].setAttribute('selected', true);
const tr = elem.parentNode.parentNode;
const rowId = tr.getAttribute("data-uniqueId");
const row = $('#table').bootstrapTable('getRowByUniqueId', rowId);
row['type'] = elem.outerHTML;
$('#table').bootstrapTable('updateByUniqueId', [{id: rowId, row: row}]);
});
I'm trying to add a new set of rows below the original one's and have a delete function together w/ the add function. Luckily I bumped into an article of w3schools : http://www.w3schools.com/jsref/met_table_insertrow.asp
However it adds the new cells above the original one's, how can I tweak it to make it work?
CODE:
<table id="myTable" border="1">
<tr>
<td>Row1 cell1</td>
<td>Row1 cell2</td>
</tr>
<tr>
<td>Row2 cell1</td>
<td>Row2 cell2</td>
</tr>
<tr>
<td>Row3 cell1</td>
<td>Row3 cell2</td>
</tr>
</table><br>
<button onclick="myCreateFunction()">Create row</button>
<button onclick="myDeleteFunction()">Delete row</button>
<script>
function myCreateFunction()
{
var table = document.getElementById("myTable");
{
var row = table.insertRow(0);
var cell1 = row.insertCell(0);
var cell2 = row.insertCell(1);
cell1.innerHTML = "NEW CELL1";
cell2.innerHTML = "NEW CELL2";
}
}
function myDeleteFunction()
{
document.getElementById("myTable").deleteRow(0);
}
</script>
insertRow() takes the position of the new row as an (optional) parameter. So, if you want the new row at the end of the table, insert an according index like this:
var row = table.insertRow( table.rows.length );
Example Fiddle
In your code you set an index of 0, which by definition is the first row.
Here's the jQuery solution.... if you want it.
HTML
<table border="1" id="myTable">
<thead>
<tr>
<td>Col 1</td>
<td>Col 2</td>
</tr>
</thead>
<tbody>
</tbody>
</table>
<br>
<input type="button" onclick="addRow()" value="Add row" />
JavaScript
var rowNo = 1;
function addRow()
{
$('#myTable tbody').append('<tr><td>Row #'+ rowNo +'</td>'+
'<td>Row #'+ rowNo +'</td></tr>');
rowNo++;
}
Live Demo
If you are using jQuery then use .after() with :eq(int) and for removing you can use .remove() but if you want to remove only newly added rows then you can use :gt(int) method:
$(function () {
$('#create').on('click', function () {
var table = $('#myTable')[0];
var rows = table.rows.length;
var row = '<tr><td>'+ rows +'</td><td>'+ rows +'</td></tr>';
$('#myTable').find('tr:eq(2)').after(row);
});
$('#delete').on('click', function () {
$('#myTable').find('tr:gt(2)').get(0).remove();
});
});
Using the above script you have to give your buttons specific ids #create for row creation and #delete for delete button like suggested below.
<button id='create'>Create row</button>
<button id='delete'>Delete row</button>
Note:
Unobtrusive javascript is better. Inline scripting should be avoided.
Demo fiddle
Updates:
Instead of hardCode in :eq(2) and :gt(2) we can cache the length of the trs in table:
$(function () {
var o = $('#myTable').find('tr:last').index(); // cache it here
$('#create').on('click', function () {
var table = $('#myTable')[0];
var rows = table.rows.length;
var row = '<tr><td>' + rows + '</td><td>' + rows + '</td></tr>';
$('#myTable').find('tr:eq(' + o + ')').after(row); // place it here
});
$('#delete').on('click', function () {
$('#myTable').find('tr:gt(' + o + ')').get(0).remove(); // and here
});
});
Demo fiddle with cached trs
$('#myTable').find('tr:last').index(); this line gets the last tr's index at the dom ready which is in this case 2 because .index() is 0 based.
var row = table.insertRow(0); // 0 represent the 0th index and hence it add at top
change it to
var tdsLength = table.getElementsByTagName('tr').length;
var row = table.insertRow(tdsLength); //change it to last index
or
var row = table.insertRow(-1);
From Docs, If index is -1 or equal to the number of rows, the row is appended as the last row.
JSFiddle
Change the code in:
var row = table.insertRow(0);
to:
var row = table.insertRow(-1);
Maybe use jQuery .prepend() function? Check it here: http://api.jquery.com/prepend/