javascript: add a numbered row to a table - javascript

I would like to add a row to a table with 4 cells: indexnumber, firstname, lastname and points. As a newbie in Javascript I am complety lost in textnodes, childs and other Dom elements. Who can help creating a dynamic indexnumber like 1,2,3 in the first column etc..
var button = document.getElementById("addRow");
button.onclick = addRowFunc;
var firstName = document.getElementById("firstN");
var lastName = document.getElementById("lastN");
var points = document.getElementById("pnt");
function addRowFunc() {
var tabel = document.getElementById("myTable");
var row = tabel.insertRow(-1);
var cel1 = row.insertCell(0);
var cel2 = row.insertCell(1);
var cel3 = row.insertCell(2);
var cel4 = row.insertCell(3);
cel1.value = function () {
for (var i = 1; i < rij.length; i++) {
//createTextNode ..
}
}
cel2.innerHTML = firstName.value;
cel3.innerHTML = lastName.value;
cel4.innerHTML = points.value;
}
<table id="myTable">
<tr>
<th>Rownumber</th>
<th>FirstName</th>
<th>LastName</th>
<th>Points</th>
</tr>
</table>
<br />
<br />
<br />
FirstName <input type="text" id="firstN" /><br />
LastName <input type="text" id="lastN" /><br />
Points <input type="text" id="pnt" /> <br />
<br />
<button type="button" id="addRow">Add</button>

One approach to the problem you're facing, that of showing the number of the table-row element can be solved using CSS, with the following rules:
tbody {
counter-reset: rownumber;
}
tr {
counter-increment: rownumber;
}
td:first-child::before {
content: counter(rownumber, decimal);
}
The above defines the counter, rownumber and has it be reset via the <tbody> element; so if rows are appended over multiple <tbody> elements then the <tr> descendants of each will be numbered independently of each other. If you'd prefer a continuous count of all <tr> elements then simply move the counter-reset rule up to the <table> element, or to any other (ideally the closest possible) ancestor within which you require a cumulative count.
This counter is incremented, by 1, in each <tr> element, and then shown in the ::before pseudo-element of the first <td> child of each <tr>. The second argument to counter() is the type of counter you wish to use (see this answer for the (current) possible options: https://stackoverflow.com/a/16943843/82548 (disclaimer: it's one of my answers, the second Snippet will allow you to see the results of different counter types).
So, that part covered I've also rewritten – I'd like to say revised or refactored, but that would be, at best, an understatement – your posted code into the following function. Code explained in the comments:
// a named function to call:
function addRow() {
// using 'let' to declare variables, this is mostly a
// matter of personal preference in this case, and if
// 'let' is unavailable to you, or your users, can be
// replaced with 'var'.
// here we define a 'details' Object to hold the
// variables from the <input> elements we find
// later:
let details = {},
// we use document.querySelector() to retrieve the first,
// if any, elements matching the supplied CSS selector;
// this is the element to which new content will be added:
target = document.querySelector('#myTable tbody'),
// and again we use document.querySelector() to find the
// element we'll be cloning in order to append the new
// new content:
source = document.querySelector('#myTable tfoot tr.template')
// we pass (Boolean) true as an argument in order to copy
// the descendants of the cloned node as well as the node
// itself:
.cloneNode(true),
// here we use Array.from() to convert the Array-like
// HTMLCollection returned from document.querySelectorAll()
// (which retrieves all the elements which match the
// supplied CSS selector) into an Array:
inputs = Array.from(
document.querySelectorAll('form label input')
);
// we make use of the Array, via Array methods such as,
// here, Array.prototype.forEach(), which iterates over
// the elements of the Array:
inputs.forEach(
// using an Arrow function, rather than the traditional
// anonymous function; here 'input' refers to the current
// Array element of the Array of <input> elements over
// which we're iterating.
// here we update the details Object, by adding a new
// key (details[input.id]) and setting the value of that
// key to the value (input.value) held in the <input>:
input => details[input.id] = input.value
);
// here we convert the Array-like NodeList of child-
// elements of the source (the <tr> element we cloned
// earlier) into an Array, again using Array.from, and
// then iterating over those elements using, again,
// Array.prototype.forEach():
Array.from(source.children).forEach(
// in this Arrow function we're naming the
// current Array-element 'cell', the name is
// purely a personal choice, and can be almost
// anything, so long as it's valid in JavaScript.
// here we set the text-content of the current
// cell (<td> element) to be equivalent to the
// value held in the details Object at the same
// custom data-* attribute, here data-from, as
// the current <td> (details.cell.dataset.from);
// if there is no key of that name, we set the
// text to an empty String (''):
cell => cell.textContent = details[cell.dataset.from] || ''
);
// we append the newly modified <tr> element to
// the target element (the <tbody>):
target.appendChild(source);
// and here we iterate over the <input> elements:
inputs.forEach(
// and set the value of each <input> back to
// its default value, the value it held on
// page-load in order to save the user having
// to first delete existing content before
// entering new content to add:
input => input.value = input.defaultValue
);
}
document.querySelector('#addRow').addEventListener('click', addRow);
function addRow() {
let details = {},
target = document.querySelector('#myTable tbody'),
source = document.querySelector('#myTable tfoot tr.template')
.cloneNode(true),
inputs = Array.from(
document.querySelectorAll('form label input')
);
inputs.forEach(
input => details[input.id] = input.value
);
Array.from(source.children).forEach(
cell => cell.textContent = details[cell.dataset.from] || ''
);
target.appendChild(source);
inputs.forEach(
input => input.value = input.defaultValue
);
}
document.querySelector('#addRow').addEventListener('click', addRow);
body {
box-sizing: border-box;
}
label {
display: block;
width: 55%;
overflow: hidden;
margin: 0 0 0.5em 0;
}
table {
table-layout: fixed;
width: 90%;
margin: 1em auto;
border-collapse: collapse;
}
label input {
width: 50%;
float: right;
}
th,
td {
border-left: 1px solid #000;
border-bottom: 1px solid #000;
line-height: 2em;
height: 2em;
}
th {
text-align: center;
}
th::after {
content: ': ';
}
td:first-child,
th:first-child {
border-left-color: transparent;
}
tbody {
counter-reset: rownumber;
}
tbody tr {
counter-increment: rownumber;
}
tbody td:first-child::before {
content: counter(rownumber, decimal);
}
tfoot tr.template {
display: none;
}
<form action="#">
<fieldset>
<legend>Add new details:</legend>
<label>FirstName
<input type="text" id="firstN" />
</label>
<label>LastName
<input type="text" id="lastN" />
</label>
<label>Points
<input type="text" id="pnt" />
</label>
<button type="button" id="addRow">Add</button>
</fieldset>
</form>
<table id="myTable">
<thead>
<tr>
<th>Rownumber</th>
<th>FirstName</th>
<th>LastName</th>
<th>Points</th>
</tr>
</thead>
<tfoot>
<tr class="template">
<td></td>
<td data-from="firstN"></td>
<td data-from="lastN"></td>
<td data-from="pnt"></td>
</tr>
</tfoot>
<tbody>
</tbody>
</table>
JS Fiddle demo.
References:
CSS:
Automatic counters and numbering.
:first-child pseudo-class.
JavaScript:
Array.from().
Array.prototype.forEach().
Arrow functions.
document.querySelector().
document.querySelectorAll().
EventTarget.addEventListener().
HTMLElement.dataset API.
Node.appendChild().
let statement.
Node.cloneNode().
`Node.textContent.
var statement.

Here's the easiest way to get how nodes and DOM work :)
var table = document.getElementById('myTable');
var row = document.createElement('tr');
var cell1 = document.createElement('td');
var cell2 = document.createElement('td');
var cell3 = document.createElement('td');
var cell4 = document.createElement('td');
cell1.innerHTML = '1';
cell2.innerHTML = '2';
cell3.innerHTML = '3';
cell4.innerHTML = '4';
row.appendChild(cell1);
row.appendChild(cell2);
row.appendChild(cell3);
row.appendChild(cell4);
table.appendChild(row);
so let's assume you have an Array of data formatted like:
data = [
{
indexNumber: 1,
firstName: 'Bon',
lastName: 'Jovi',
points: 50,
},
{
indexNumber: 2,
firstName: 'Ann',
lastName: 'Hathaway',
points: 60,
},
];
now you can process this Array in a forEach cycle:
var table = document.getElementById('myTable');
data.forEach(function(element) {
var row = document.createElement('tr');
var cell1 = document.createElement('td');
var cell2 = document.createElement('td');
var cell3 = document.createElement('td');
var cell4 = document.createElement('td');
cell1.innerHTML = element.indexNumber;
cell2.innerHTML = element.firstName;
cell3.innerHTML = element.lastName;
cell4.innerHTML = element.points;
row.appendChild(cell1);
row.appendChild(cell2);
row.appendChild(cell3);
row.appendChild(cell4);
table.appendChild(row);
});

to insert a new row use append
<table id="mytable">
<tr><td >1</td> <td >sd</td> <td >sd</td> <td >sd</td></tr>
<tr><td >2</td> <td >sd</td> <td >sd</td> <td >sd</td></tr>
<tr><td >3</td> <td >sd</td> <td >sd</td> <td >sd</td></tr>
</table>
add this with jquery
var total_rows = $('#mytable tr').length;
var new_row = parseInt(total_rows)+parseInt(1);
var yourdata_variable = "<tr><td >"+new_row+"</td> <td >sd2</td> <td >sd2</td> <td >sd2</td></tr>";
$('#mytable').append(yourdata_variable);
if you just want to use javascript
var yourdata_variable = same as above;
var table = document.getElementById('mytable').append(yourdata_variable);
comment if this is what you want.

Related

editable table cells html

I am making a table in html that uses javascript to add a new row, have editable cells and then allows the user to click save and the edits to the cells become saved. However, the code I wrote only works and does this in the first row that is added. When I attemp to add a new row, my save() function no longer works. I know this is because I am accessing the table cells with ids and so multiple elements have the same id, but I do not know how to fix it.
<table id="myTable">
<tr>
<th>1</th>
<th>2</th>
</tr>
</table>
<button onclick="addRow()">Add row button</button>
<script>
function addRow() {
let tableRef = document.getElementById('myTable');
let newRow = tableRef.insertRow(-1);
let firstcell = newRow.insertCell(0);
firstcell.setAttribute("id","firstcell")
let secondcell = newRow.insertCell(1);
secondcell.setAttribute("id","secondcell")
var input1=document.createElement('input')
secondcell.appendChild(input1);
var btn = document.createElement('button');
btn.type = "button";
btn.className = "save";
let btntext= document.createTextNode("save button");
btn.appendChild(btntext)
btn.setAttribute("onclick","save()")
firstcell.appendChild(btn);
}
function save(){
input1rref=document.getElementById("input1")
input1value=input1rref.value
input1text=document.createTextNode(input1value);
x=document.getElementById("secondcell")
x.replaceChild(input1text,input1rref)
}
</script>
<style>
table{
padding:10px;
border: 2px solid black;
}
button{
padding:10px 20px;
}
</style>
If you have more than one form control (ex. <input>, <select>, <button>, etc), wrap everything in a <form>. Use .class, tagName, name, and [attribute] to reference elements. As you can see in the example below, id is used only once to reference the <form>, but even that could've been referenced by name easily.
Figure I - HTML Layout
<form id='formID' name='formName'>
<input id='inputID' name='formControl' type='number'>
<button name='formControl' type='button'>GO!</button>
<table class='tableClass'>
<tr><td></td><td></td></tr>
</table>
<select name='formControl'>
<option value='1'>I</option>
<option value='2'>II</option>
<option value='3'>III</option>
<option value='4'>IV</option>
</select>
<output name='outputName'></output>
</form>
Figure II - Referencing Elements
// Reference with .querySelector() to get the first element match
// "." prefix for class
const table = document.querySelector('.tableClass');
// "#" prefix for id
const form = document.querySelector('#formID');
// "[]" wrap for other attributes
const input = document.querySelector('[name="formControl"]');
// No prefix or wrap for tagName
const button = document.querySelector('button');
// Use .querySelectorAll() to gather all matches into a NodeList
const options = document.querySelectorAll('option')
// Reference the third <option>
const third = options[2]
// HTMLFormElement Interface
const form = document.forms.formID;
const formALT1 = document.forms.formName;
const formALT2= document.forms['formName'];
const formALT3 = document.forms[0];
// References all form controls under <form>
const fc = form.elements
// Reference form controls id, name, or index notation
const input = fc.inputID;
const output = fc.outputName;
const select = fc[2];
// HTMLFormControlsCollection Interface
// Group all form controls that share the same name
const allFCNames = fc.formControl
Read the following
Events
Event Delegation
Inline Event Handlers are Garbage
HTMLFormElement
HTMLFormControlsCollection
Form Controls
Details are commented in example
/**
* #desc Utility function that will append a given htmlString into
* a given element and renders it into HTML.
* #param {string|object} selector - If passed as a string it will
* find element by CSS selector. If passed as a variable, it
* will reference a DOM Object. This is the object to append
* HTML to.
* #param {string} htmlString - A string that resembles HTML layout
*/
function setHTML(selector, htmlString) {
const node = typeof selector === 'string' ?
document.querySelector(selector) :
selector;
node.insertAdjacentHTML('beforeend', htmlString);
}
// Reference the <form>
const tForm = document.forms.interface;
// Bind the click event to <form>
tForm.onclick = action;
// Bind the change event to <form>
tForm.onchange = format;
// Event handler passes Event Object by default
function action(e) {
// e.target is the <button> the user clicked
// The click event is delegated to the <button> clicked by className
switch (e.target.className) {
case 'add':
addRow(e);
break;
case 'delete':
deleteRow(e);
break;
case 'edit':
case 'edit open':
editRow(e);
break;
default:
break;
}
}
function addRow(e) {
// Reference <tbody>
const tData = document.querySelector('.data');
// Reference <thead>
const tHead = tData.parentElement.createTHead();
// Get the number of columns
let cQty = tHead.rows[0].cells.length;
// Define the value/text of each <option> in an array
const opts = ["Select Benchmark", "Cash", "Munis", "Bonds", "Stocks", "Commods", "Alts"];
// Reference inserted <tr>
let tRow = tData.insertRow();
// Iterate >cQty< times
for (let i = 0; i < cQty; i++) {
// Reference inserted <td>
let tCel = tRow.insertCell();
/*
Determine which is the current <td> by (i)ndex
Each case creates a <td> and it's content
Some elements have too many attributes so using .setAttribute()
would bloat the code signifigantly. In those cases render the
HTML instead (case 1, case 2, and case 4)
*/
switch (i) {
case 0:
const sel = document.createElement('select');
sel.name = 'benchmark';
opts.forEach(o => {
let opt = new Option(o, o);
sel.add(opt);
});
tCel.append(sel);
break;
case 1:
const tilt = `<input name='tilt' class='open' type='number' min='0' step='.01' placeholder='0.00'>`;
setHTML(tCel, tilt);
break;
case 2:
const comment = `<input name='comment' class='open' type='text' placeholder='Enter comment'>`;
setHTML(tCel, comment);
break;
case 3:
const log = document.createElement('time');
log.textContent = new Date().toLocaleString();
log.className = 'log';
tCel.append(log);
break;
case 4:
const buttons = `
<button name='btn' class='delete' type='button' title='Delete Row'>➖</button>
<button name='btn' class='edit open' type='button' title='Edit Row'>✏️</button>`;
setHTML(tCel, buttons);
break;
default:
break;
}
}
}
// Here we simply find the closest <tr> and remove it
function deleteRow(e) {
e.target.closest('tr').remove();
}
// This function just toggles the 2 <input> [readonly] attributes
function editRow(e) {
e.target.classList.toggle('open');
const row = e.target.closest('tr');
const inputs = row.querySelectorAll('input');
inputs.forEach(inp => {
inp.toggleAttribute('readonly');
inp.classList.toggle('open');
});
}
// Formats a value into a float with 2 decimal places
function format(e) {
if (e.target.matches('[name="tilt"].open')) {
e.target.value = parseFloat(e.target.value).toFixed(2);
}
}
html {
font: 300 2.5vmin/1 'Segoe Ui';
}
table {
table-layout: fixed;
border-collapse: collapse;
width: 96%;
}
th {
border-bottom: 3px solid black;
}
th:first-of-type,
th:nth-of-type(2) {
width: 11rem;
}
th:nth-of-type(3) {
width: 17rem;
}
th:nth-of-type(4) {
width: 13rem;
}
th:nth-of-type(5) {
width: 9rem;
}
td {
text-align: center;
padding: 4px;
}
input,
select,
button {
display: inline-flex;
align-items: center;
font: inherit;
}
button {
cursor: pointer;
}
input {
border: 0;
}
.open {
border-radius: 4px;
outline: 3px inset blue;
outline-offset: 1px;
}
[name="tilt"] {
width: 9rem;
text-align: right;
font-family: Consolas;
}
[name="comment"] {
width: 17rem;
}
time {
width: 10rem;
}
<form id='interface'>
<table>
<thead>
<tr>
<th>Benchmark</th>
<th>Tilt</th>
<th>Comment</th>
<th>Time Log</th>
<th><button name='btn' class='add' type='button'>➕ Add Row</button></th>
</tr>
</thead>
<tbody class='data'></tbody>
</table>
</form>
Reason is you are assigning the same ids to the controls in multiple rows (as the user adds rows).
What you should do:
Keep track of the number of rows and append row number to the controls in all the setAttribute("id"... lines. Example:
superassetCell.setAttribute("id", "benchmarkcell");
// should be
superassetCell.setAttribute("id", "benchmarkcell" + row_number);
getElementById works by definition for element with the unique id.
When calling save method, each row should pass the row number as argument to save.
Checkout this question

Add Input to Each Column of HTML Table

I am trying to add an input field to each cell of my HTML table when I add a new row. The problem is that each time I click the button it only adds an input field to the first column. If I change the index number it only works for either the first or last column, but no columns in between.
<table id="table">
<tr>
<th id="item">Item</th>
<th>Ounces (Oz)</th>
<th>Grams (g)</th>
<th>Fluid Ounces (FOz)</th>
<th>Milliliters (mL)</th>
<th>Drops</th>
<th>Completed</th>
</tr>
</table>
<p>Click button to test funtionality.</p>
<button onclick="AddRow()">Click Me</button>
<script>
function AddRow() {
// Get ID for table from HTML file
var table = document.getElementById("table");
// Count number of columns in table
var columnNumber = document.getElementById("table").rows[0].cells.length;
// Add row to last row in table
var row = document.getElementById("table").insertRow(-1);
// Create Input field in table
var newInput = document.createElement("INPUT");
newInput.setAttribute("type", "text");
newInput.setAttribute("placeholder", "Raw Good Name");
newInput.classList.add("TableInput");
// Add columns to new row matching header
for (i = 1; i <= columnNumber; i++) {
var firstColumn = row.insertCell(0).appendChild(newInput);
}
}
</script>
Clone the input or simplify the script
I made the HTML valid and use an eventListener as recommended
const tb = document.getElementById("tb");
const columnNumber = document.querySelectorAll("#table thead tr th").length - 1;
const inp = '<td><input type="text" placeholder="Raw Good Name" class="TableInput"/></td>';
let cnt = 1;
document.getElementById("add").addEventListener("click",() => {
tb.innerHTML += `<tr>
<td class="right">${cnt++}</td>
${[...Array(columnNumber).keys()].map(i => inp).join("")}
</tr>`
})
.right {
text-align: right;
}
<table id="table">
<thead>
<tr>
<th id="item">Item</th>
<th>Ounces (Oz)</th>
<th>Grams (g)</th>
<th>Fluid Ounces (FOz)</th>
<th>Milliliters (mL)</th>
<th>Drops</th>
<th>Completed</th>
</tr>
<thead>
<tbody id="tb">
</tbody>
</table>
<p>Click button to test funtionality.</p>
<button type="button" id="add">Click Me</button>
You need to be creating the input and appending it to the cell within the loop that creates the cells so that more than one will be created.
/* This is only here for display purposes in the Stack Overflow environment */
input { width:5em; }
<table id="table">
<tr>
<th id="item">Item</th>
<th>Ounces (Oz)</th>
<th>Grams (g)</th>
<th>Fluid Ounces (FOz)</th>
<th>Milliliters (mL)</th>
<th>Drops</th>
<th>Completed</th>
</tr>
</table>
<p>Click button to test funtionality.</p>
<button onclick="AddRow()">Click Me</button>
<script>
function AddRow() {
// Get ID for table from HTML file
var table = document.getElementById("table");
// Count number of columns in table
var columnNumber = document.getElementById("table").rows[0].cells.length;
// Add row to last row in table
var row = document.getElementById("table").insertRow(-1);
// Add columns to new row matching header
// Loop should start at 0 and continue as long as you are less than
// the array length
for (i = 0; i < columnNumber; i++) {
// Create Input field in table
var newInput = document.createElement("INPUT");
// newInput.setAttribute("type", "text"); <-- Not needed: type="text" is the default
// newInput.setAttribute("placeholder", "Raw Good Name"); <-- See following line for simpler syntax
newInput.placeholder = "Raw Good Name";
newInput.classList.add("TableInput");
// If we're not on the first of last column
if(i !== 0 && i < columnNumber - 1){
newInput.type = "number"; // Make the input a number
}
row.insertCell(0).appendChild(newInput);
}
}
</script>

How can I add <td> tags to my html table with JavaScript?

I'm trying to use the insertcell method to add a column to my table but either I'm getting the syntax wrong or it isn't working. I wondered if anyone could explain where I am going wrong?
The table body in the html is populated dynamically with some other JavaScript but I don't think this is the problem as I've tested grabbing some content from that table with an alert box and it works (commented out below):
<!DOCTYPE html>
<script type="text/javascript" src="fullstationxyparser.js">
</script>
<html>
<body>
<table border=1>
<thead>
<tr>
<td>Element Name</td>
<td>x</td>
<td>y</td>
<td>testCol</td>
</tr>
</thead>
<tbody id="stationlist">
</tbody>
</table>
</body>
</html>
function addStationNames() {
var myTable = document.getElementById("stationlist");
var stationListRows = myTable.getElementsByTagName('tr');
for (var i = 1; i < stationListRows.length; i++) {
var cell = stationListRows[i].getElementsByTagName('td');
var stationName = cell[0].innerHTML; //get station id from element Name column
var currentRow = stationListRows[i];
var newCol = currentRow.insertcell(-1);
newCol.innerHTML = stationName;
//alert(stationName);
}
}
In Firefox developer tools, I get TypeError: "currentRow.insertcell is not a function". Perhaps I can't use the insertcell method on a row collection?
In general you can call the insertRow() method on a Table DOM element, followed by calls to the insertCell() method as shown below to dynamically add <td> tags to your table with JavaScript.
Be careful to call insertCell() (with capital C) rather than insertcell() as you are currently doing:
const table = document.querySelector('table');
/* Insert new row */
const row = table.insertRow();
/* Insert cells (td) for row */
const td0 = row.insertCell(0);
const td1 = row.insertCell(1);
const td2 = row.insertCell(2);
const td3 = row.insertCell(3);
/* Populate cells with data */
td0.innerText = 'Foo';
td1.innerText = '3';
td2.innerText = '6';
td3.innerText = 'success';
<table border="1">
<thead>
<tr>
<td>Element Name</td>
<td>x</td>
<td>y</td>
<td>testCol</td>
</tr>
</thead>
<tbody>
</tbody>
</table>
Specific to your code, some other changes to consider might be as listed in this code snippet:
function addStationNames() {
/* Condense table row access into single query */
const stationRows = document.querySelectorAll("#stationlist tr");
stationRows.forEach((stationRow, i) => {
/* Skip first row */
if(i === 0) { return; }
/* Get station name from text of first cell */
const stationName = stationRow.querySelector('td:first-child').innerText;
/* Insert last cell on row and assign station name */
stationRow.insertCell(-1).innerText = stationName;
});
/*
Old code:
for (let i = 1; i < stationListRows.length; i++) {
var cell = stationListRows[i].getElementsByTagName('td');
var stationName = cell[0].innerHTML;
var currentRow = stationListRows[i];
var newCol = currentRow.insertcell(-1);
newCol.innerHTML = stationName;
}
*/
}
addStationNames();
<!-- set table id to stationlist -->
<table border="1" id="stationlist">
<thead>
<tr>
<td>Element Name</td>
<td>x</td>
<td>y</td>
<td>testCol</td>
</tr>
<tr>
<td>90's pop</td>
<td>232</td>
<td>543</td>
</tr>
</thead>
<tbody>
<!-- Remove id from tbody -->
</tbody>
</table>
An alternative to the answer above (which is totally fine) is this method, which is also a more general method of creating any html element:
const table = document.getElementById('one');
const newRow = document.createElement("tr");
let newCell = document.createElement("td");
newCell.textContent = "first cell";
let newCell2 = document.createElement("td");
newCell2.textContent = "second cell";
newRow.appendChild(newCell);
newRow.appendChild(newCell2);
table.appendChild(newRow);
https://jsfiddle.net/zgaosdbv/

Add table row programmatically doesn't work correctly in javascript

I have a form like that:
<form>
<table id="table">
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>SVNr</th>
</tr>
<tr>
<td contenteditable="true">Jill</td>
<td contenteditable="true">Smith</td>
<td class="svnr" contenteditable="true">50</td>
<td><input type="submit" value="Remove" onclick="DeleteRow(this)"></td>
</tr>
<tr>
<td contenteditable="true">Eve</td>
<td contenteditable="true">Jackson</td>
<td class="svnr" contenteditable="true">94</td>
<td><input type="submit" value="Remove" onclick="DeleteRow(this)"></td>
</tr>
</table>
<input type="button" value="Save Changes">
</form>
This one works perfectly. Futhermore, I want to add table rows to my table programmatically.
I do it this way:
count = numberOfRows;
formular[count] = new Object();
formular[count]["Firstname"] = document.getElementById("Firstname").value;
formular[count]["Lastname"] = document.getElementById("Lastname").value;
formular[count]["SVNr"] = document.getElementById("SVNr").value;
var table = document.getElementById("table");
var TR = table.insertRow(count);
var TD = document.createElement("td");
TD.setAttribute("contenteditable", "true");
var TD2 = document.createElement("td");
TD2.setAttribute("contenteditable", "true");
var TD3 = document.createElement("td");
TD3.setAttribute("contenteditable", "true");
TD3.className = "svnr";
var TD4 = document.createElement("td");
var TXT = document.createTextNode(formular[count]["Firstname"]);
var TXT2 = document.createTextNode(formular[count]["Lastname"]);
var TXT3 = document.createTextNode(formular[count]["SVNr"]);
var Input = document.createElement("input");
Input.type = "submit";
Input.value = "Remove";
Input.onclick = "DeleteRow(this);";
TD.appendChild(TXT);
TR.appendChild(TD);
TD2.appendChild(TXT2);
TR.appendChild(TD2);
TD3.appendChild(TXT3);
TR.appendChild(TD3);
TD4.appendChild(Input);
TR.appendChild(TD4);
document.getElementById("Firstname").value = "";
document.getElementById("Lastname").value = "";
document.getElementById("SVNr").value = "";
Also this code is working well. The only problem is that the Remove function doesn't work correctly for the table rows I added programmatically.
My Removing function looks like that:
function DeleteRow(o) {
var p = o.parentNode.parentNode;
p.parentNode.removeChild(p);
}
This function removes ALL programmatically added values if I press the button for one of them. This function works for the 2 entries in the form I didn't add programmatically but as I said, if I press the Remove button for one of added entries, it removes all programmatically added rows and not just the chosen one.
You need to add in something to uniquely identify each tr. You could set a custom attribute on each tr, set a unique id, etc. and pass the unique value to the delete function.
In addition you may find it easier to work with tables by using the DOMTable properties & methods:
http://www.javascriptkit.com/domref/tableproperties.shtml
http://www.javascriptkit.com/domref/tablemethods.shtml

How to put an onclick event for a HTML table row created dynamically through java script.?

I am new to javascript.
Can anyone help me to implement an onclick event on click of a HTML table row created through javascript?
Kindly note that I am inserting the data in table cells using innerHTML.
Below is the code snippet of what i have tried.?
Java Script function:
function addRow(msg)
{
var table = document.getElementById("NotesFinancialSummary");
var finSumArr1 = msg.split("^");
var length = finSumArr1.length-1;
alert("length"+ length);
for(var i=1; i<finSumArr1.length; i++)
{
var row = table.insertRow(-1);
var rowValues1 = finSumArr1[i].split("|");
for(var k=0;k<=10;k++)
{
var cell1 = row.insertCell(k);
var element1 = rowValues1[k];
cell1.innerHTML = element1;
}
}
for(var i=1; i<rowCount; i++)
{
for(var k=0;k<=10;k++)
{
document.getElementById("NotesFinancialSummary").rows[i].cells[k].addEventListener("click", function(){enableProfileDiv()}, false);
}
}
}
HTML table code in jsp :
<TABLE id="NotesFinancialSummary" width="800px" border="1" align="left" >
<tr >
<th>Symbol</th>
<th>Claimant</th>
<th>MJC</th>
<th>S</th>
<th>Type</th>
<th>Indemnity Resv</th>
<th>Indemnity Paid</th>
<th>Medical Resv</th>
<th>Medical Paid</th>
<th>Legal Resv</th>
<th>Legal Paid</th>
</tr>
<tr>
<td>
</td>
<TD> </TD>
<TD> </TD>
<TD> </TD>
<TD> </TD>
<TD> </TD>
<TD> </TD>
<TD> </TD>
<TD> </TD>
<TD> </TD>
<TD> </TD>
</tr>
</table>
<table id="table"></table>
$("#table").append("<tr><td>Hi there</td></tr>");
$("#table").on( "click", "tr", function(){
// do something
alert( $(this).children("td:first").text() );
});
Any time the click event bubbles up to <table id="table">, this function will be called (no matter if the <tr>s are inserted dynamically, or hard coded).
This will require the jQuery library
http://jquery.com/
http://api.jquery.com/on/
One way to do it would be using document.createElement
Instead of doing:
yourParentElement.innerHTML = "<tr>Something</tr>";
You can do
var tr = document.createElement("tr");
tr.innerHTML = "Something";
tr.onclick = function() {
//code to be executed onclick
};
yourParentElement.appendChild(tr);
Another way, would be to use an id (only if you're doing this once, you don't want duplicated ids):
yourParentElement.innerHTML = "<tr id='someId'>Something</tr>";
document.getElementById("someId").onclick = function() { //fetch the element and set the event
}
You can read more about events here, but just so you have an idea onclick will only let you set one function.
If you want a better solution you can use something like addEventListener, but it's not crossbrowser so you may want to read up on it.
Lastly, if you want to set up an event on every tr you can use:
var trs = document.getElementByTagName("tr"); //this returns an array of trs
//loop through the tr array and set the event
after you insert your <tr> using innerHTML, create a click event listener for it.
document.getElementById("the new id of your tr").addEventListener("click", function() {
what you want to do on click;
});
Something like this: http://jsfiddle.net/gnBtr/
var startEl = document.getElementById('start');
var containerEl = document.getElementById('container');
var inner = '<div id="content" style = "background: pink; padding:20px;" > click on me </div>'
// Function to change the content of containerEl
function modifyContents() {
containerEl.innerHTML = inner;
var contentEl = document.getElementById('content');
contentEl.addEventListener("click", handleClickOnContents, false);
}
// listenting to clikc on element created via innerHTML
function handleClickOnContents() {
alert("you clicked on a div that was dynamically created");
}
// add event listeners
startEl.addEventListener("click", modifyContents, false);
Check it out:
$('#your_table_id tbody').on('click', 'tr', function (e) {
$('td', this).css('background-color', 'yellow');
} );
css:
tr:hover td{
background-color: lightsteelblue !important;
}
It works fine for me, specially when I'm using jquery dataTable pagination.

Categories

Resources