Iterate and append to table - javascript

Hello i am trying to append some strings from an array to an table. I want every array item to have its own tr element.
The things i have tried so far is this:
const body = document.body
const table = document.createElement('table')
const tr = document.createElement('tr')
const th = document.createElement('th')
const form = document.createElement('form')
const label = document.createElement('label')
table.innerHTML
body.append(table)
tr.innerHTML
table.append(tr)
const thText = ["ID", "First name", "Last name", "Email", "Phone number", "Actions"]
thText.forEach((text)=>{
th.innerHTML = text
tr.append(th);
})
When console.log(th) i get <th> Actions </th> 6 times. but the only thing that is rendered is Actions once.
Would love to get some help. Thanks :)

You're only creating one th element. You'd need to create one for each iteration, so, within the loop:
thText.forEach(text => {
const th = document.createElement('th')
th.innerHTML = text
tr.append(th)
})

There's a few different ways to do this. Here's an example of one way. This method does a few things differently then your example.
It creates and uses a thead element for proper table formatting.
It uses a basic for loop method.
It creates a new th element for each header label in the array, then it appends it to the tr element.
It uses textContent instead of innerHTML
const headerLabels = ["ID", "First name", "Last name", "Email", "Phone number", "Actions"]
const body = document.body
const table = document.createElement('table')
const thead = document.createElement('thead')
const tr = document.createElement('tr')
thead.append(tr)
table.append(thead)
body.append(table)
for (let i = 0; i < headerLabels.length; i++) {
let th = document.createElement('th')
th.textContent=headerLabels[i]
tr.append(th)
}
td, th {
border: 1px solid #ddd;
padding: 8px;
}
tr:nth-child(even) {
background-color: #f2f2f2;
}
th {
padding-top: 12px;
padding-bottom: 12px;
text-align: left;
background-color: #4CAF50;
color: white;
}
<body>
<script src="main.js"></script>
</body>

Related

How to get `<th>` instead of `<td>`?

I want to have first element of my row as <th> I am doing this but I am getting <td> as my first element. What I am doing wrong?
Basically I want something like this <tr><th><b>Table Header</b></th><td>item1</td><td>item2</td><\tr>
var table = document.getElementById("data");
var row = table.insertRow(-1);
var cell1 = row.insertCell(0);
$("#table td:first").append('<th><b>Table Header</b></th>');
You just need to not use insertCell in your question
var table = document.getElementById("data");
var row = table.insertRow(-1);
$(row).append('<th>Table Header</th>');
<table id="data"></table>
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
You can create your own method to insert a <th>
// insert <TH> method, at your oxn risk
HTMLTableRowElement.prototype.insert_th_Cell = function(index)
{
let cell = this.insertCell(index)
, c_th = document.createElement('th')
cell.replaceWith(c_th)
return c_th
}
//---------------------------------------
let thead = myTable.createTHead()
, tBody = myTable.createTBody()
, rowHead = thead.insertRow()
;
rowHead.insertCell()
rowHead.insert_th_Cell().textContent = 'c1'
rowHead.insert_th_Cell().textContent = 'c2'
rowHead.insert_th_Cell().textContent = 'c3'
let nRow = tBody.insertRow()
nRow.insert_th_Cell().textContent = 'line'
nRow.insertCell().textContent = 'AA'
nRow.insertCell().textContent = 'BB'
nRow.insertCell().textContent = 'CC'
table {
border-collapse : collapse;
margin : 2em 1em;
}
td,th {
padding : .2em .8em;
border : 1px solid darkblue;
}
thead {
background-color: aquamarine;
}
tbody th{
background-color: orchid;
}
<table id="myTable"></table>

Fill table rows with values from an array

I'm creating a table using JavaScript DOM and I need to insert all the values from the array (thValues) to each of the TH contained in a TR (table row). How I can do it?
let thValues = ["Text 1", "Text 2", "Text 3", "Text 4", "Text 5", "Text 6"];
let pickTableZone = document.getElementById("tableDetails");
let table = document.createElement("table");
pickTableZone.appendChild(table);
table.setAttribute("class", "table table-responsive-sm table-striped");
let tableBody = document.createElement("tbody");
table.appendChild(tableBody); //adding tbody to table
//for the length of thValues create table rows
for (let i = 0; i < thValues.length; i++) {
let tableRow = document.createElement("tr");
tableBody.appendChild(tableRow); //adding TR to TBODY
let tableHead = document.createElement("th");
tableRow.appendChild(tableHead); //adding TH to TR
tableHead.setAttribute("scope", "row"); //adding attributes to TH
let text = document.createTextNode(thValues[0]); //Assign each text from the thValues in each TH from the TR's
tableHead.appendChild(text); //adding text to TH
let tableData = document.createElement("td");
tableRow.appendChild(tableData); //adding TD to TR
let textInTD = document.createTextNode("Time 1");
tableData.appendChild(textInTD); //adding text to TD
}
table, th, td {
border: 1px solid gray;
border-collapse: collapse;
padding: 1rem;
}
<div id="tableDetails">
You need two loops: one to populate the head row with th cells; one to create the body rows with td cells. As it stands, you're creating a new row for each header value instead of putting all of them in a single row. You're also putting your head cells in tbody instead of thead.
Here is how you could create the header row.
const thValues = ["Text 1", "Text 2", "Text 3", "Text 4", "Text 5", "Text 6"];
const pickTableZone = document.getElementById("tableDetails");
const table = document.createElement("table");
pickTableZone.appendChild(table);
table.setAttribute("class", "table table-responsive-sm table-striped");
const tableHead = document.createElement("thead");
table.appendChild(tableHead); //adding thead to table
const headRow = document.createElement("tr");
tableHead.appendChild(headRow); // Row for the head cells.
// Add each header.
for (let i = 0; i < thValues.length; ++i) {
const headCell = document.createElement("th");
headRow.appendChild(headCell); //adding head cell to head row
const text = document.createTextNode(thValues[i]);
headCell.appendChild(text); //adding text to TH
}
const tableBody = document.createElement("tbody");
table.appendChild(tableBody); //adding tbody to table
// for each row of data
// add a tr to tbody
// for each column (e.g. thValues.length)
// add a td to the tr
table, th, td {
border: 1px solid gray;
border-collapse: collapse;
padding: 1rem;
}
<div id="tableDetails"></div>
It's not clear from your post what you want to put in the tbody since you're just repeating "Time 1" over and over. I've therefore left some pseudocode for populating the body.
As an aside, you should use const instead of let unless you plan on reassigning the variable (for a number of reasons).
I realized what I was missing in my code to achieve what I wanted. I forgot to add an i to let text = document.createTextNode(thValues[i]);
let thValues = ["Text 1", "Text 2", "Text 3", "Text 4", "Text 5", "Text 6"];
let pickTableZone = document.getElementById("tableDetails");
let table = document.createElement("table");
pickTableZone.appendChild(table);
table.setAttribute("class", "table table-responsive-sm table-striped");
let tableBody = document.createElement("tbody");
table.appendChild(tableBody); //adding tbody to table
//for the length of thValues create table rows
for (let i = 0; i < thValues.length; i++) {
let tableRow = document.createElement("tr");
tableBody.appendChild(tableRow); //adding TR to TBODY
let tableHead = document.createElement("th");
tableRow.appendChild(tableHead); //adding TH to TR
tableHead.setAttribute("scope", "row"); //adding attributes to TH
let text = document.createTextNode(thValues[i]); //Assign each text from the thValues in each TH from the TR's
tableHead.appendChild(text); //adding text to TH
let tableData = document.createElement("td");
tableRow.appendChild(tableData); //adding TD to TR
let textInTD = document.createTextNode("Time 1");
tableData.appendChild(textInTD); //adding text to TD
}
table, th, td {
border: 1px solid gray;
border-collapse: collapse;
padding: 1rem;
}
<div id="tableDetails">

In a grid built in javascript and html, how do I assign a new text-node value to all cells in the grid that fulfils a condition

I am relatively new to DOM manipulation with JS and html. Here I am having to build a 10 * 10 grid, with sequential numbers in each cells representing its text node. And the requirement is that, when I click on any cell in the grid, if its text node value is 5 or a multiple of 5, then the text node of this cell and also all other cells in the grid which are multiples of 5 should be replaced with a "**".
Here's my code till now, but I am just failing to implement the conditional replacement of the cell's text node value on a click event. And here's my jsfiddle
Many thanks in advance.
<html>
<head>
<meta charset="utf-8">
<title>Grid with random numbers</title>
<style>
#grid {
margin: 10px;
font-size: 1.25em;
}
table {
border-collapse: collapse;
border: 1px solid #7f7f7f;
}
td {
border: 1px solid #7f7f7f;
width: 50px;
height: 50px;
text-align: center;
}
</style>
</head>
<body>
<div id="grid"></div>
<script>
let totalRows = 10;
let cellsInRow = 10;
let min = 1;
let max = 100;
function drawTable() {
let cellNumber = 1;
let grid = document.getElementById('grid');
let tbl = document.createElement("table");
// Create rows in the table
for (var r = 0; r < totalRows; r++) {
let row = document.createElement("tr");
row.setAttribute('id', (r));
// In each row now create cells
for (var c = 0; c < cellsInRow; c++) {
let cell = document.createElement("td");
let cellText = document.createTextNode(cellNumber++);
let cellFillingStar = document.createTextNode("**");
// each cell should have its 'id' attribute set, as its corresponding cellText value
cell.setAttribute('id', (cellNumber - 1));
cell.appendChild(cellText);
row.appendChild(cell);
// Code to check that each cell got its 'id' attribute set, as its corresponding cellText value.
cell.addEventListener(
"click",
function(e) {
var id = e.target.id;
if (id % 5 == 0) {
$('.table').each(function() {
$(this).find('id').each(function() {
alert("Multiple of 5");
cell.appendChild(cellFillingStar);
})
})
}
},
false);
}
tbl.appendChild(row);
}
grid.appendChild(tbl);
}
window.onload = drawTable;
</script>
</body>
First of all there are some error in your script, like you're trying to loop on a .table object that doesn't exist, as table has no class.
I've tried to simplify it a little bit, using jquery.
the main snippet I've added is this one:
$( "#grid table tr td" ).on( "click", function(event) {
var id = event.target.id;
if (id % 5 == 0) {
$( "#grid table tr td" ).each(function( index ) {
if ($(this).text() % 5 == 0) {
$(this).text($(this).text()+'**');
}
});
}
});
where you assign the event to all td elements, and then, based on their content or id value, you change the text of all relevant td that are multiple of 5.
here is the full working example:
https://jsfiddle.net/xpvt214o/88139/

Creating an HTML table using JavaScript and JSON

I am trying to create an HTML table using JavaScript from a JSON input, however, it's not working out for me.
I am using a marker in the HTML. This will get populated from an innerHTML call in Javascript:
for (var i = 0; i < json.data.length; i++) {
listItem = json.data[i].number + "--" + "( Widget " + json.data[i].widget_id + ") x " + " " + json.data[i].pence_price + " GBP" + json.data[i].number * json.data[i].pence_price + " GBP";
table.push(listItem);
}
document.getElementById('updateOrder').innerHTML = table;
This gives me the following output:
11--Widget 8 x 10GBP 110GBP, 10--Widget 9 x 10GBP 100GBP
What I want is the following:
11--Widget 8 x 10GBP 110GBP
10--Widget 9 x 10GBP 100GBP
Where the number, widget and cost are left-aligned, and the total is right-aligned. I also want separate orders on separate lines.
The data in the JSON is:
{"id":"9518","order_id":"11380","widget_id":"9","number":"10","pence_price":"12"}
I've been pulling my hair out with this; any help or guidance would be appreciated.
var json = {data:{a: {"id":"9518","order_id":"11380","widget_id":"9","number":"10","pence_price":"12"},b:{"id":"9518","order_id":"11380","widget_id":"9","number":"10","pence_price":"12"},c: {"id":"9518","order_id":"11380","widget_id":"9","number":"10","pence_price":"12"}}}
var i,
item,
listItem = "";
for (i in json.data){
item = json.data[i];
listItem += "<div class='table'><div>"+item.number+"--"+"( Widget "+item.widget_id+") x "+" "+item.pence_price+" GBP</div><div class='right'>"+item.number*item.pence_price+" GBP</div></div>";
}
document.getElementById('updateOrder').innerHTML=listItem;
#updateOrder{
padding: 2px;
background: orange;
}
.table{
width: 100%;
background: green;
display: table;
}
.table > div{
display: table-cell;
}
.right{
background: tomato;
}
<div id="updateOrder"></div>
I created a bit larges template which gives you a possible way to create a table, add some styling to it, and do some potential calculations.
I did my best to add as much comments as possible describing what the code is doing.
Since you mentioned you wanted an html table, it is created with the basic table element, and some basic styles were added to differentiate between header, rows and footer
// the data used in this demo
var data = [{
"id": "9518",
"order_id": "11380",
"widget_id": "9",
"number": "10",
"pence_price": "12"
},
{
"id": "9518",
"order_id": "11380",
"widget_id": "9",
"number": "10",
"pence_price": "12"
}
];
function createTable(target, data, columns) {
// gets the elements required based on id for the target div
// and creates the table, thead, tbody & tfoot for the table
let element = document.getElementById(target),
table = document.createElement('table'),
thead = document.createElement('thead'),
header = document.createElement('tr'),
tbody = document.createElement('tbody'),
tfoot = document.createElement('tfoot');
// creates the header
columns.forEach(column => {
// and creates the cells in the header, adding title and class
let cell = document.createElement('td');
cell.innerHTML = column.title;
cell.className = column.class;
header.appendChild(cell);
});
thead.appendChild(header);
// totals is used for the totals for the footer
var totals = {};
for (let i = 0; i < data.length; i++) {
// creates the single rows
let row = document.createElement('tr');
columns.forEach(column => {
// and for each column creates the cell itself
let cell = document.createElement('td');
let value;
// checks what to display
if (column.field) {
// only a property on the data
value = data[i][column.field];
} else if (column.value) {
// a function with a callback value
value = column.value(data[i])
}
// if it should calculate totals, it will do so here
if (column.calculateTotal) {
// in case the column is unknown, it's initialized as 0
// warning: all values will be whole numbers
totals[column.field] = (totals[column.field] || 0) + parseInt( value );
}
// if it has a template, we will replace the %0 with value
// this template function supports only 1 value to be "templated"
if (column.template) {
value = column.template.split('%0').join(value);
}
// set the cell value
cell.innerHTML = value;
// set the class (used to align, for example)
cell.className = column.class;
// add cell to row
row.appendChild(cell);
});
// add row to tbody
tbody.appendChild(row);
}
// empty object would mean false, so only if totals needed to be calculated
// would it create the footer here
if (totals) {
let row = document.createElement('tr');
columns.forEach( column => {
let cell = document.createElement('td'), value = '';
if (column.calculateTotal) {
value = totals[column.field];
if (column.template) {
// can still use the row template
value = column.template.split('%0').join(value);
}
}
cell.innerHTML = value;
cell.className = column.class;
row.appendChild( cell );
});
tfoot.appendChild( row );
}
table.appendChild(thead);
table.appendChild(tbody);
table.appendChild(tfoot);
// set the table on the target element
// warning, calling create table twice will create 2 tables under eachother
element.appendChild(table);
}
// call the create table, with the:
// - target: id in html -> 'target'
// - data: an array defining your data itself
// - columns: an array of objects describing how the table should look
// - title: header
// - field (optional): which property it should show
// - value (optional): callback function that receives a row and should return a value
// - calculatedValue (optional): bool indicating if columns should be summed
// - template (optional): any text you wish to add to your data?
createTable('target', data, [{
title: 'id',
field: 'id',
class: 'left'
},
{
title: 'order',
field: 'order_id',
class: 'left'
},
{
title: 'widget',
field: 'widget_id',
class: 'left'
},
{
title: 'number',
field: 'number',
class: 'center'
},
{
title: 'price',
field: 'pence_price',
class: 'right',
template: '%0 GBP'
},
{
title: 'total',
value: (row) => parseInt(row['number']) * parseInt(row['pence_price']),
class: 'right',
template: '%0 GBP',
calculateTotal: true
}
]);
.left {
text-align: left;
}
.right {
text-align: right;
}
thead tr {
background-color: #777;
}
thead tr td {
font-weight: bold;
color: #fff;
}
tfoot tr td {
font-weight: bold;
}
table td {
padding: 5px;
border-bottom: solid #efefef 1px;
}
<div id="target">
</div>

createElement background image

I am trying to create a table width javascript and createElement().
My problem is that it does not set any background image (just plain white).
However, if I set the innerHTML of the to an image tag with same path, it works!
create : function () {
var tbody = document.createElement('tbody');
for(i in this.map) {
var tr = document.createElement('tr');
for(j in this.map[i]) {
var td = document.createElement('td');
var cell = this.map[i][j];
td.style.color = "red";
console.log("gfx/tile_"+this.backgrounds[cell]+".png");
td.style.backgroundImage = "url(gfx/tile_"+this.backgrounds[cell]+".png);";
td.innerHTML = "j";
tr.appendChild(td);
}
tbody.appendChild(tr);
}
this.gameDOMelm.appendChild(tbody);
}
I also have another problem that there's space between each ROW in the table.
Here's the DOM Element I'm appending to:
<table id="gameField" cellpadding="0" cellspacing="0"></table>
And the CSS
* {padding: 0; margin: 0;}
td {
min-width: 32px;
min-height: 32px;
width: 32px;
height: 32px;
}
These problems occur both in Chrome and FF # ubuntu 11.04.
No errors shows in javascript console.
jack
Try "url('gfx/tile_"+this.backgrounds[cell]+".png')" (with single quotes around the URL).

Categories