I want to add/remove rows in a table dynamically. I have javascript function to add and remove the rows. But, I want the delete button beside every single row so that I can delete a particular row.
ANd I want to add a row only if the first row is completely filled.
function to remove row
function removeRowFromTable()
{
var tbl = document.getElementById('tblSample');
var lastRow = tbl.rows.length;
if (lastRow > 2) tbl.deleteRow(lastRow - 1);
}
function to add rows:
function addRow(tableID) {
var table = document.getElementById(tableID);
var rowCount = table.rows.length;
var row = table.insertRow(rowCount);
var cell1 = row.insertCell(0);
var element1 = document.createElement("input");
element1.type = "text";
cell1.appendChild(element1);
var cell2 = row.insertCell(1);
var element2 = document.createElement("input");
element2.type = "text";
cell2.appendChild(element2);
}
my table:
<table id="tableId">
<tr><td>Host Name</td><td>Directory</td></tr>
<tr><td><input type="text"/></td><td><input type="text"/></td></tr>
<tr><td><input type="button" value="+" onclick="addRow(tableId)"/></td>
<td><input type="button" value="-" onclick="removeRowFromTable()"/></td></tr>
</table>
Any help is appreciated! Thanks in Advance!!!
If you put a delete button on each row, then:
<tr>
<td><input type="button" value="Delete row" onclick="deleteRow(this)">
<td><input type="text">
<td><input type="text">
</tr>
And the deleteRow function can be:
function deleteRow(el) {
// while there are parents, keep going until reach TR
while (el.parentNode && el.tagName.toLowerCase() != 'tr') {
el = el.parentNode;
}
// If el has a parentNode it must be a TR, so delete it
// Don't delte if only 3 rows left in table
if (el.parentNode && el.parentNode.rows.length > 3) {
el.parentNode.removeChild(el);
}
}
BTW, if all your rows have the same content, it will be much faster to add a row by cloning an existing row:
function addRow(tableID) {
var table = document.getElementById(tableID);
if (!table) return;
var newRow = table.rows[1].cloneNode(true);
// Now get the inputs and modify their names
var inputs = newRow.getElementsByTagName('input');
for (var i=0, iLen=inputs.length; i<iLen; i++) {
// Update inputs[i]
}
// Add the new row to the tBody (required for IE)
var tBody = table.tBodies[0];
tBody.insertBefore(newRow, tBody.lastChild);
}
You can avoid a lot of cross browser headaches by using jquery. Here is a sample.
http://jsfiddle.net/piyushjain7/gKJEs/
Javascript has this really useful function called deleteRow where if you know the index you are deleting from, you can simply input that number, and then it'll delete that specific row (index's starting at 0 - tbl.rows.length).
I also found a nice example that uses it in action. You can adjust it to fit your needs though (although his uses checkboxes which might be a lot cleaner than just making a button next to every single row). I don't encourage you to blatantly copy the code so if there is anything that confuses you, please let us know. Hope this helps.
EDIT: I didn't see you wanted to add rows after you found out the last row was completely filled. I'll update my answer when I figure that out. However, the basic idea of that is to check if the <td> tag has text in it (perhaps check if the text inside the tag isn't a blank or if there is a <td> tag at all and then if it isn't empty, make a new <tr> element else don't.
See http://jsfiddle.net/9gnAx/
HTML & JavaScript (body):
<table id="tableId">
<tr>
<th>Host Name</th>
<th>Directory</th>
<td><input class="add" type="button" value="+" /></td>
</tr>
<tr>
<td></td><td></td>
<td><input class="add" type="button" value="+" /></td>
</tr>
</table>
<script type="text/javascript">
(function(){
var els=getElementsByClassName("add","tableId");
for(var i=0;i<els.length;i++){
els[i].onclick=addRow;
}
els[0].onclick();
})();
</script>
CSS (head):
.add,.del{
width:25px;
}
JavaScript (head):
function getElementsByClassName(c,el){
if(typeof el=='string'){el=document.getElementById(el);}
if(!el){el=document;}
if(el.getElementsByClassName){return el.getElementsByClassName(c);}
var arr=[],
allEls=el.getElementsByTagName('*');
for(var i=0;i<allEls.length;i++){
if(allEls[i].className.split(' ').indexOf(c)>-1){arr.push(allEls[i])}
}
return arr;
}
function killMe(el){
return el.parentNode.removeChild(el);
}
function getParentByTagName(el,tag){
tag=tag.toLowerCase();
while(el.nodeName.toLowerCase()!=tag){
el=el.parentNode;
}
return el;
}
function delRow(){
killMe(getParentByTagName(this,'tr'));
}
function addRow() {
var table = getParentByTagName(this,'table')
var lastInputs=table.rows.length>2?
table.rows[table.rows.length-2].getElementsByTagName('input'):[];
for(var i=0;i<lastInputs.length-1;i++){
if(lastInputs[i].value==''){return false;}
}
var rowCount = table.rows.length;
var row = table.insertRow(rowCount-1);
var cell1 = row.insertCell(0);
var element1 = document.createElement("input");
element1.type = "text";
cell1.appendChild(element1);
var cell2 = row.insertCell(1);
var element2 = document.createElement("input");
element2.type = "text";
cell2.appendChild(element2);
var cell3 = row.insertCell(2);
var element3 = document.createElement("input");
element3.type = "button";
element3.className="del";
element3.value='-';
element3.onclick=delRow;
cell3.appendChild(element3);
}
Update:
RobG has made me realize that getParentByTagName throws an error if there isn't any parent with the nodeName passed.
If you want a more general getParentByTagName, which doesn't throw errors, you can use
function getParentByTagName(el,tag){
tag=tag.toLowerCase();
while(el&&el.nodeName.toLowerCase()!=tag){
el=el.parentNode;
}
return el||null;
}
And when you call the function you should check if the result is null.
Updated jsfiddle: http://jsfiddle.net/9gnAx/1/
Related
Apologies if something similar has been posted but I am trying to delete a row the button is on and not just the last row as the search results seem to give me.
I have the following code that adds to an HTML table but onclick doesn't work, the delete button doesn't work and addRow doesn't function. Why not?
java code
function addRow() {
var table = document.getElementById("createOrderTable");
var rowCount = table.rows.length;
var row = table.insertRow(rowCount);
... other cells ...
var cell4 = row.insertCell(3);
var btn = document.createElement("input");
btn.type = "button";
btn.value = "Close";
btn.onclick = deleteRow('createOrderTable', rowCount);
cell4.appendChild(btn);
}
function deleteRow(id, row) {
document.getElementById(id).deleteRow(row);
}
table code
<table id="createOrderTable" width="100%">
<tr>
<th>Count</th><th>Product</th><th>Mesh</th><th>Delete</th>
</tr>
<tr>
<td>1</td><td>OL</td><td>200</td><td><button type="button" class="close" aria-hidden="true" onclick="deleteRow('createOrderTable', 1)">×</button></td>
</tr>
</table>
if I change
btn.onclick = deleteRow('createOrderTable', rowCount );
to
btn.onclick = deleteRow('createOrderTable', rowCount + 1 );
I can get the row to show but it throws
Uncaught IndexSizeError: Failed to execute 'deleteRow' on 'HTMLTableElement': The index provided (3) is greater than the number of rows in the table (3).
and doesn't show the button. I'm confused about what I'm doing wrong here.
The row index is not static, so as you delete rows, the row index of remaining rows can change if a row with a lower index is deleted. A solution is to not use rowIndex at all, and just use DOM relationships instead.
You can get a reference to the button that was clicked by passing this to the function, then go up parent nodes until you reach a TR element and delete it, e.g.
// Helper function:
function upTo(el, tagName) {
tagName = tagName.toLowerCase();
while (el && el.parentNode) {
el = el.parentNode;
if (el.tagName && el.tagName.toLowerCase() == tagName) {
return el;
}
}
return null;
}
function deleteRow(el) {
var row = upTo(el, 'tr')
if (row) row.parentNode.removeChild(row);
}
<table>
<tr>
<td>1</td><td>OL</td><td>200</td>
<td><button type="button" onclick="deleteRow(this)">×</button></td>
</tr>
<tr>
<td>2</td><td>AB</td><td>400</td>
<td><button type="button" onclick="deleteRow(this)">×</button></td>
</tr>
</table>
You can also use event delegation and put a single listener on the table, then use the associated event object's target property to see if the event was initiated by a click on a button with class close. If so, call deleteRow and pass the element reference as a parameter as for the above.
You shoud modify your code like this:
btn.onclick = deleteRow;
And the deleteRow declaration to this:
function deleteRow() {
this.parentElement.parentElement.remove();
}
UPDATE
Check working example.
To delete the current row that the button belongs to
Change onclick of <button> to :
onclick="this.parentNode.parentNode.parentNode.deleteRow(this.parentNode.parentNode.rowIndex)"
or change button in html like:
<input type="button" onclick="deleteRow(this)">X</button>
or by JavaScript code using
btn.setAttribute('onclick','deleteRow(this)');
Delete function is like:
function deleteRow(el) {
var tbl = el.parentNode.parentNode.parentNode;
var row = el.parentNode.parentNode.rowIndex;
tbl.deleteRow(row);
}
Why when I check the checkbox it works fine when I uncheck it nothing happen
<form method="get">
<table id="row">
<tr><th colspan="2" >Location</th></tr>
<tr><td>Country:</td><td><select id="country" name ="country" style="width:200px"></select></td></tr>
<tr><td>City:</td><td><select name ="city" id ="state"></select></td></tr>
<script language="javascript">
populateCountries("country", "state");
</script>
<tr><td></td><td><input onclick="myFunction()" type="checkbox" name="manualentry" value="manualentry" >Manual Entry</td></tr>
<script>
var table = document.getElementById("row");
function myFunction() {
if (document.getElementsByTagName('manualentry').checked = true) {
document.getElementById("row").deleteRow(2);
var row = table.insertRow(2);
var cell1 = row.insertCell(0);
var cell2 = row.insertCell(-1);
cell1.innerHTML = "City:";
cell2.innerHTML = '<input type="text" >';
} else {
document.getElementById("row").deleteRow(2);
var row = table.insertRow(2);
var cell1 = row.insertCell(0);
var cell2 = row.insertCell(1);
cell1.innerHTML = "City:";
cell2.innerHTML = '<select name ="city" id ="state"></select>';
}
}
</script>
<tr ><td colspan="2" align="right" > <input type="submit" value="Submit"></td></tr>
</table>
</form>
A couple things. GetElementsByTagName is the wrong function call, that method is used to get an array of elements by their actual HTML tag. Use GetElementsByName instead. Also, this call will return an array, so you need to specify which index it is (it will be index 0). Since checked is already a boolean value, you do not need to specify == true.
Replace if (document.getElementsByTagName('manualentry').checked = true)
with if (document.getElementsByName('manualentry')[0].checked)
You forgot a = in the if condition:
if (document.getElementsByTagName('manualentry').checked = true) {
try
if (document.getElementsByTagName('manualentry').checked == true) {
I am trying to create a table with an input field dynamically but my code ends up creating an empty table.
var calcDiv = document.getElementById("calc_div");
var calcTab = document.createElement('TABLE');
var tbody = document.createElement('TBODY');
var calcForm = document.createElement('FORM');
calcForm.id = "calculator_form";
//calc display
var tr = document.createElement('TR');
var td = document.createElement('TD');
td.colspan = "4";
var comp = document.createElement('INPUT');
comp.type = "text";
comp.value = 0;
comp.disabled = true;
comp.id = "compDisplay";
td.appendChild(comp); //THIS DOESN'T SEEM TO WORK
tr.appendChild(td);
tbody.appendChild(tr);
calcForm.appendChild(comp);
calcTab.appendChild(tbody);
calcTab.style.width = "500px";
calcTab.style.height = "500px";
calcDiv.appendChild(calcTab);
You were missing a line and were incorrectly appending another. In:
tr.appendChild(td);
tbody.appendChild(tr);
calcForm.appendChild(comp);
You needed to:
tr.appendChild(td);
tbody.appendChild(tr);
calcTab.appendChild(tbody); <-- append the tbody to the table
calcForm.appendChild(calcTab); <-- append the table to the form
jsFiddle example
This produces the HTML:
<div id="calc_div">
<table style="width: 500px; height: 500px;">
<tbody>
<tr>
<td>
<input type="text" disabled="" id="compDisplay">
</td>
</tr>
</tbody>
</table>
</div>
Note that you may also want to use td.setAttribute('colspan','4'); instead of td.colspan = "4";
Maybe because you are adding the input named "comp" again in the form after two rows? "calcField.addChild(comp)"
What's happening is you're appending comp to the td, then appending it to the form after that. This removes it from the table it was in and puts it in the form, which isn't attached anywhere in your document.
Here's a sample with the appending to the form commented out. Or perhaps you'd prefer to append the form to the td instead.
I think this method will help you out. I've coded it so that the appendChild follows the DOM tree. Take a look. Note: I created a variable to append the target "calc_div" to the document body. Feel free to take that out.
var div = document.body.appendChild(document.createElement('div'));
div.id = "calc_div";
var table = div.appendChild(document.createElement('table'));
table.style.width = "500px";
table.style.height = "500px";
var tbody = table.appendChild(document.createElement('tbody'));
var trow = tbody.appendChild(document.createElement('tr'));
var tcell = trow.appendChild(document.createElement('td'));
tcell.colSpan = "4";
var input = tcell.appendChild(document.createElement('input'));
input.id = "compDisplay";
input.type = "text";
input.value = 0;
input.disabled = true;
I am trying to create dynamic select boxes that contain the same data, however, only the first select box contains the data and not the others.
Can someone assist me as to how I would populate the others accordingly please.
<input type="button" value="Add" onclick="addRow('dataTable')" />
<input type="button" value="Delete" onclick="deleteRow('dataTable')" />
<?php $i= 1; ?>
<table id="dataTable">
<tr>
<td><input type="checkbox" name="chkbox[]"/></td>
<td> 1 </td>
<td><select name="fireman[]"><option value=""></option><?php require("php/fireman_list.php"); ?></select> </td>
</tr>
</table>
JS CODE
<script language="javascript">
function addRow(tableID) {
var table = document.getElementById(tableID);
var rowCount = table.rows.length;
var row = table.insertRow(rowCount);
var cell1 = row.insertCell(0);
var element1 = document.createElement("input");
element1.type = "checkbox";
element1.name="chkbox[]";
cell1.appendChild(element1);
var cell2 = row.insertCell(1);
cell2.innerHTML = rowCount + 1;
var cell3 = row.insertCell(2);
var element2 = document.createElement("select");
element2.type = "text";
element2.name = "fireman[]";
cell3.appendChild(element2);
}
function deleteRow(tableID) {
try
{
var table = document.getElementById(tableID);
var rowCount = table.rows.length;
for(var i=0; i<rowCount; i++)
{
var row = table.rows[i];
var chkbox = row.cells[0].childNodes[0];
if(null != chkbox && true == chkbox.checked)
{
table.deleteRow(i);
rowCount--;
i--;
}
}
}
catch(e)
{
alert(e);
}
}
</script>
Err... From what I understand of your code, I am not quite sure you're using the right tool for the job.
You have PHP on the server side that is meant to generate HTML pages, so why bother to do it in JavaScript? Even with the help of JQuery, adding DOM elements dynamically is a messy, verbose and tedious business.
If you want your page to display only part of its contents, the usual way of doing it is to have all the possible contents created on the page, and mask the parts that you don't want (using CSS attributes).
I assume you don't plan to allow to create on your page an infinite number of... Mmmm... whatever these dynamic table represent?
If you can set a limit to, say, 10 instances, you can create these 10 instances with a simple PHP loop (or even by copy-pasting the HTML code for a proof of concept test), and then replace your creation/destruction process with a show/hide mechanism.
Initially, only the first instance will be shown. the "Add" button will make the next one visible, and the "Delete" button will make the last one invisible.
If you index your table instances by Id (i.e. "DataTable_0", "DataTable_1", etc.), it is really easy to switch them on and off with CSS, like so:
function hide_table (table_number)
{
document.getElementById ("DataTable_"+table_number).style.display = 'none';
}
You can make them reappear just as easily using block instead of none for display property.
What do you think?
you need to change the addRow function so that it accepts two additional parameters which are arrays consists of the values and Text for options of the created select item.
selValue will be the array of values of options in select and
selText will be the array of Text of options in select
Let the code be:
function addRow(tableID, selValue, selText)
{
var table = document.getElementById(tableID);
var rowCount = table.rows.length;
var row = table.insertRow(rowCount);
var cell1 = row.insertCell(0);
var element1 = document.createElement("input");
element1.type = "checkbox";
element1.name="chkbox[]";
cell1.appendChild(element1);
var cell2 = row.insertCell(1);
cell2.innerHTML = rowCount + 1;
var cell3 = row.insertCell(2);
var element2 = document.createElement("select");
element2.type = "text";
element2.name = "fireman[]";
//dynamically adding data from arrays passed
for(var i=0; i<selValue.length;i++)
{
op=document.createElement("option");
op.text= selValue[i];
op.value= selText[i];
cell3.add(op);
}
// dynamic adding end
cell3.appendChild(element2);
}
I want to add a new row on button click to a table. New Row will have one textbox and one drop-down. Dropdown (select element)'s options to be added from session attribute.
I am able to add textbox using following function.
function addRow(btn) {
var parentRow = btn.parentNode.parentNode;
var table = parentRow.parentNode;
var rowCount = table.rows.length;
var row = table.insertRow(rowCount);
var cell1 = row.insertCell(0);
var element1 = document.createElement("input");
element1.type = "text";
element1.name="abc";
cell1.appendChild(element1);
var cell3 = row.insertCell(1);
var element2 = document.createElement("select");
var option1 = document.createElement("option");
option1.innerHTML = "Option1";
option1.value = "1";
element2.appendChild(option1, null);
}
I have one session attribute "types". I want to add one drop down list as other column to the row where options are to be added from types. I am setting the attribute "types" when page gets loaded.
I am using Java Servlet for server side.
Any help is appreciated.
<c:forEach items="${types}" var="type">
If u have session attribute "types" then u can do like this. Post ur remaining coding so i can update my answer.
var Type = 'option 1';
function AddRow() {
$('#tblTest').append(
'<tr><td>' +
'<input type="text" />' +
'<select><option>' + Type + '</option></select>' +
'</td></tr>');
}
<table id="tblTest">
<tr>
<td>
<input type="text" name="data1" value="TempData" />
</td>
<td>
<input type="button" value="Add" onclick="AddRow()" />
</td>
</tr>
</table>