I am trying to insert another row into a table with footer.
Here is my code:
function submit(){
/* Some code here with declarations & value assignings*/
let tble = document.getElementById("tabl");
let newEl = document.createElement("tr");
newEl.innerHTML="<td>"+nowSr+"</td> <td>"+taskForm+"</td> <td>"+tagForm+"</td> <td>Rs. "+amountForm+"</td>";
tble.appendChild(newEl, tble.lastElementChild.previousSibling.lastElementChild);
}
My function gives me below result:
As you can see (IN INSPECT ELEMENTS WINDOW) the new row is inserted after the footer. How to add it properly
after the last row in the table?
Don't insert the element directly to the <table> element, but select the <tbody> instead.
You can do that like that:
function submit(){
let tble = document.getElementById("tabl");
let newEl = document.createElement("tr");
newEl.innerHTML="<td>"+nowSr+"</td> <td>"+taskForm+"</td> <td>"+tagForm+"</td> <td>Rs. "+amountForm+"</td>";
tble.querySelector('tbody').appendChild(newEl, tble.lastElementChild.previousSibling.lastElementChild);
}
But you shouldn't use innerHTML to create the row (it could create an XSS vulnerability), use innerText or textContent instead. But that means that you have to create the <td>s differently:
function submit(){
let tble = document.getElementById("tabl");
let newEl = document.createElement("tr");
appendTD(newEl, nowSr);
appendTD(newEl, taskForm);
appendTD(newEl, tagForm);
appendTD(newEl, "Rs. "+amountForm);
tble.querySelector('tbody').appendChild(newEl, tble.lastElementChild.previousSibling.lastElementChild);
}
function appendTD(tr, text){
const td = document.createElement('td')
td.innerText = text
tr.appendChild(td)
}
Try puhsing to the tbody intead of the table directly
function addTableRow(){
const tbody = document.querySelector('#myTable tbody')
const newRow = document.createElement('tr')
newRow.innerHTML = `<td>Foo</td><td>Bar</td>`
tbody.appendChild(newRow)
}
<table id="myTable">
<thead>
<tr>
<th>Helo</th>
<th>World</th>
</tr>
</thead>
<tbody>
<tr>
<td>Foo</td>
<td>bar</td>
</tr>
</tbody>
</table>
<button onclick="addTableRow()">Add row</button>
Related
What I am trying to do is on button press I will add 4 text elements, each text element in its own cell; beneath its corresponding column. Eg. "Name" column will have the name of the product beneath it. Refer to picture attached below.
My problem is - On button press my 4 elements are created but only one cell is created and it has all 4 of my elements in it. If someone could help me find the solution that would be amazing!
Relevant code attached below.
<div id="inventory">
<!--Here is where we shall store our data-->
<table class="table">
<tr class="head-row">
<th class="table-head">Name</th>
<th class="table-head">Price</th>
<th class="table-head">ID</th>
<th class="table-head">Quantity</th>
</tr>
<div>
Javascript:
//Items
let items = [
["chips",25,3163,1],
["Pork", 25 , 316 , 1],
["Crackers",5,400,1]
];
addButton.addEventListener('click', addItem);
function addItem(){
let table = document.querySelector(".table");
let row = document.createElement('tr');
row.classList.add("row");
let cell = document.createElement('td');
cell.classList.add('item-properties')
//Create our table item
items[1].forEach(itemProperty =>{
let textNode = document.createTextNode(itemProperty);
cell.appendChild(textNode);
row.appendChild(cell);
});
table.appendChild(row);
}
You need a td element for each value.
//Items
let items = [
["chips", 25, 3163, 1],
["Pork", 25, 316, 1],
["Crackers", 5, 400, 1]
];
document.getElementById('add').addEventListener('click', addItem);
function addItem() {
let table = document.querySelector(".table");
let row = document.createElement('tr');
row.classList.add("row");
let cell = document.createElement('td');
cell.classList.add('item-properties')
//Create our table item
items[1].forEach(itemProperty => {
let td = document.createElement('td');
let textNode = document.createTextNode(itemProperty);
td.appendChild(textNode);
row.appendChild(td);
});
table.appendChild(row);
}
<button id="add">Add</button>
<div id="inventory">
<!--Here is where we shall store our data-->
<table class="table">
<tr class="head-row">
<th class="table-head">Name</th>
<th class="table-head">Price</th>
<th class="table-head">ID</th>
<th class="table-head">Quantity</th>
</tr>
</table>
</div>
I got the problem all solved!
Just had to create the cell variable inside the forEach loop, so now it will loop through and create a cell each time- then add my textNode to that cell. If anyone has any pointers or alternate solutions more than happy to hear!
function addItem(){
let table = document.querySelector(".table");
let row = document.createElement('tr');
row.classList.add("row");
//Create our table item
items[1].forEach(itemProperty =>{
let textNode = document.createTextNode(itemProperty);
cell = document.createElement('td'); //ADDED THIS
cell.appendChild(textNode);
row.appendChild(cell);
console.log(itemProperty);
});
table.appendChild(row);
}
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>
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/
I am using Javascript to dynamically create a table, and want to make a header-style cell at the beginning of each row. So my question is how I can do this, seeing as insertCell creates only a normal <td> element and not a <th>.
Some things I've tried (via the Tryit editor at w3schools; I have no reason to suspect that any other usage will behave differently) and didn't work:
I've seen a suggestion to create the <th> element independently and then add it to the <tr> element as a child. When I do this, however, it is not added as a table cell, i.e. it is not affected by the table border, does not count toward the array of cells (i.e. if you do insertCell(1), it inserts after the first cell not counting the <th>), and does not get the special bold/center format for a <th> cell.
I've attempted to use insertCell to make a dummy cell and then replaceChild with an independently created cell; this had the same result as above.
I've tried to make a <td> cell via insertCell and simply bold and center it manually, but myCell.style.fontWeight="bold" and myCell.align="center" don't seem to work (they just end the function, as bad commands do in JavaScript), and likewise trying to use CSS doesn't work. So maybe I just have bad syntax or something, but I've got no clue what to do. Any help would be appreciated.
Attempt 1:
<!DOCTYPE html>
<html>
<body>
<p>Click the button to insert new cell(s) at the end of the table row.</p>
<table border="1">
<th>1</th>
<td>2</td>
</tr>
<tr id="myRow">
</tr>
<tr>
</table><br>
<button onclick="myFunction()">Try it</button>
<script>
function myFunction()
{
var newRow = document.getElementById("myRow");
var header=document.createElement("th").appendChild(document.createTextNode("a"));
newRow.appendChild(header);
var enablesLoc=newRow.insertCell(0).appendChild(document.createTextNode("b"));
}
</script>
</body>
</html>
Result: "1" is bolded with a border, "2" and "b" are unbolded with a border (as they should be), "a" is unbolded with no border.
Attempt 2:
<!DOCTYPE html>
<html>
<body>
<p>Click the button to insert new cell(s) at the end of the table row.</p>
<table border="1">
<th>1</th>
<td>2</td>
</tr>
<tr id="myRow">
</tr>
<tr>
</table><br>
<button onclick="myFunction()">Try it</button>
<script>
function myFunction()
{
var newRow = document.getElementById("myRow");
var header=newRow.insertCell(0).appendChild(document.createTextNode("a"));
header.style.fontWeight="bold";
var enablesLoc=newRow.insertCell(1).appendChild(document.createTextNode("b"));
}
</script>
</body>
</html>
Result: The button adds cell "a" unbolded but not cell "b".
The following code shows everything that should get you going:
function addTable(){
var table = document.createElement("table");
var tr = document.createElement("tr");
var th = document.createElement("th");
var td = document.createElement("td");
td.innerText = "im a td";
th.innerText = "im a th";
tr.appendChild(th);
tr.appendChild(td);
table.appendChild(tr);
var out = document.getElementById("out");
out.appendChild(table);
}
You have to call the function and an div with id out <div id=out>...</div> must be in the document. Disclaimer: i only tested this code in chrome
Update to address your points
You wrote I've seen a suggestion to create the <th> element independently and then add it to the <tr> element as a child. When I do this
it is not added as a table cell what do you mean by that and what command are you using,
is not affected by the table border the reason could be because it contains not text,
does not count toward the array of cells (i.e. if you do insertCell(1) i do not understand this either. According to the specs on insertCell it insert an empty td and returns a reference. So insertCell has no array, If you try var table = document.getElementById("myTable") and then table.rows[0].cells.length it returns the number of cells including the th-cell.
it inserts after the first cell not counting the th according on my tests at least in chrome this is not the case; it depends on how you call the method: table.rows[1].insertCell(-1); adds a cell at the second row (zero based array) at the end and table.rows[2].insertCell(1); adds in the third row a cell on position 2 (again zero based) if you use table.rows[3].insertCell(0); the cell is inserted into the 4th. row at the beginning,
and does not get the special bold/center format for a th cell this was not the case for me as well
Disclaimer: i only tested this code in chrome
The html
<button onclick="addRow()">add rows</button><br />
<button onclick="addColumn()">add column</button>
<table border="1" id="myTable">
<tr>
<th>1</th>
<td>2</td>
</tr>
</table>
And the javascript
function addRow()
{
var table = document.getElementById("myTable");
var tr = document.createElement("tr");
var th = document.createElement("th");
var td = document.createElement("td");
td.innerText = "im a td";
th.innerText = "im a th";
tr.appendChild(th);
tr.appendChild(td);
table.appendChild(tr);
}
function addColumn(){
var table = document.getElementById("myTable");
var rows = table.rows;
console.log("rows", rows);
for (var i = 0; i < rows.length; ++i) {
// td = rows[i].cells;
var td = document.createElement("td");
td.innerText = i;
rows[i].appendChild(td);
}
}
Based on DOM Level 2 HTML you can not use insertCell since it Insert[s] an empty TD cell into this row. But you want to add a th
According to DOM Level 3 Core you can use appendChild since it adds the node newChild to the end of the list of children of this node. If the newChild is already in the tree, it is first removed.
So therefore you have to create the elements in the right order: create the row, add the first cell as th then add other cells as td by using append child.
You may take a look at a demo of the above code
The .appendChild() method returns the element being appended. Which means on this line:
var header=document.createElement("th").appendChild(document.createTextNode("a"));
...your header variable is actually the text node, not the th element - so then newRow.appendChild(header); appends just the text node to the row, not the new th.
Try something like this instead:
var newRow = document.getElementById("myRow");
var header = document.createElement("th");
header.appendChild(document.createTextNode("a"));
newRow.appendChild(header);
Demo: http://jsfiddle.net/PtzRL/
Note that if you actually want to append new rows then your newRow variable should not be getting a reference to an existing row in the table, you should give an id to the table:
<table id="myTable">
...and then create a new row and add that to the table:
var table = document.getElementById("myTable");
var newRow = document.createElement("tr");
table.appendChild(newRow);
Demo: http://jsfiddle.net/PtzRL/1/
(Note also that the starting html you show has an error: you're missing the first <tr> just after the <table> tag, and you have an extra <tr> just before the closing </table> tag.)
Is this what you were trying to do?
function myFunction = function() {
var newRow, newHeader, newCell;
newRow = document.getElementById("myRow");
newHeader = document.createElement("th");
newHeader.innerText = "a";
newRow.appendChild(newHeader);
newCell = document.createElement("td");
newCell.innerText = "b";
newRow.appendChild(newCell);
}
If you want the button to add new rows rather than filling in a blank row you put there already, try something like this:
HTML:
<body>
<table id="myTable" border="1">
<tr>
<th>1</th>
<td>2</td>
</tr>
</table>
<button onclick="myFunction()">Try it</button>
</body>
JavaScript:
function myFunction = function() {
var myTable, newRow, newHeader, newCell;
myTable = document.getElementById("myTable");
newRow = document.createElement("tr");
newHeader = document.createElement("th");
newHeader.innerText = "a";
newRow.appendChild(newHeader);
newCell = document.createElement("td");
newCell.innerText = "b";
newRow.appendChild(newCell);
myTable.appendChild(newRow);
}
The function need to altered like this I believe...
function myFunction()
{
var newRow = document.getElementById("myRow");
var header=document.createElement("th");
header.appendChild(document.createTextNode("a"));
newRow.appendChild(header);
var enablesLoc=newRow.insertCell(0);
enables.appendChild(document.createTextNode("b"));
}
I want to append a new row in my table using Javascript but the new row should be like my previous rows.
I am using CSS to format my rows.
If you are using jQuery it will be something like this:
$(document).ready(function() {
$("table tr:last").clone().appendTo("table");
})
Replacing table with the id or class of your table (unless you only plan to have one table).
Using good old Node.cloneNode(deep) along with HTMLTableElement.rows:
HTML:
<table id="foo">
<tbody id="bar">
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
</tbody>
</table>
JS:
var foo = document.getElementById("foo");
var bar = document.getElementById("bar");
var rows = foo.rows;
var lastRow = rows[rows.length-1];
var newRow = cloneRow(lastRow, true, bar);
function cloneRow(row, append, parent)
{
var newRow = row.cloneNode(true);
if(append)
{
if(parent)
{
parent.appendChild(newRow);
}
}
return newRow;
}
For comparison's sake, here's my code juxtaposed against the jQuery answer: http://jsperf.com/dom-methods-vs-jquery-with-tables
Let's say that your row has a css style of .row
So you could just use DOM methods to create a new tr, add the class="row" then add the appropriate amount of td
Here is a solution that avoids the use of the cloneNode method, and that do not copy the content, data or events of the previous last row, just its CSS attributes and class names.
The new row will have the same number of cell as the previous last row.
var lastRow = myTable.rows[myTable.rows.length-1];
var newRow = myTable.insertRow();
newRow.className = lastRow.className;
newRow.style.cssText = lastRow.style.cssText;
for (var i = 0; i < lastRow.cells.length; i++) {
var newCell = newRow.insertCell(i);
newCell.className = lastRow.cells[i].className;
newCell.style.cssText = lastRow.cells[i].style.cssText;
}