How to create loop that populates an HTML table with a Javascript array
I’ve been tasked with populating an HTML table using javascript arrays, but I’m having a lot of trouble understanding how to get my arrays to populate an actual HTML table. I have to create a table that has 5 menu item images, 5 menu item descriptions, and their 5 prices. I have my arrays provided below, but don’t know what functions I need to perform to get the arrays to populate the HTML table. What do you recommend I do to get them populating in an HTML table? Also, as per the assignment, I must use a numeric array to store the prices and a string array to store the image files. I think I have to perform some kind of ‘for’ loop, but I’m not sure. Thanks for all of your help, and please let me know how I can refine this question. Thanks,
//my arrays var item = ["Chicken soup", "Chicken tacos", "Chicken quesadilla", "Chicken burrito", "Chicken enchilada"]; var itemDescription = ["Delicious creamy chicken soup", "Homemade tacos", "Cheesy chicken quesadillas", "Hearty stuffed chicken burrito", "World famous chicken enchilada"]; var itemPrice = [14.99, 17.99, 15.75, 22.95, 12.55]; var imgArray = new Array(); imgArray[0] = new Image(); imgArray[0].src = 'chickensoup.jpg'; imgArray[1] = new Image(); imgArray[1].src = 'chickentaco.jpg'; imgArray[2] = new Image(); imgArray[2].src = 'chickenque.jpg'; imgArray[3] = new Image(); imgArray[3].src = 'chickenburrito.jpg'; imgArray[4] = new Image(); imgArray[4].src = 'chickenenchilada.jpg';
4 Answers 4
For starters I would recommend merging the arrays into one, to avoid any errors regarding indices.
The standard html format is of the type:
name description price imageSrc Chicken soup Delicious creamy chicken soup 14.99
So you need one loop to print all the headers. You need one loop to create a different row for each item. You need one last loop inside the row loop to add each cell (food property) to the row.
var items = [< name: "Chicken soup", description: "Delicious creamy chicken soup", price: 14.99, imageSrc: "chickensoup.jpg" >, < name: "Chicken tacos", description: "Homemade tacos", price: 17.99, imageSrc: "chickentaco.jpg" >, < name: "Chicken quesadilla", description: "Cheesy chicken quesadillas", price: 15.75, imageSrc: "chickenque.jpg" >, < name: "Chicken burrito", description: "Hearty stuffed chicken burrito", price: 22.95, imageSrc: "chickenburrito.jpg" >, < name: "Chicken enchilada", description: "World famous chicken enchilada", price: 12.55, imageSrc: "chickenenchilada.jpg" >]; var propertyList = ["name", "description", "price", "imageSrc"]; var table = document.createElement("table"); var tableHeader = document.createElement("thead"); var tableHeaderRow = document.createElement("tr"); var tableBody = document.createElement("tbody"); table.setAttribute("border", "1"); document.body.appendChild(table); table.appendChild(tableHeader); tableHeader.appendChild(tableHeaderRow); table.appendChild(tableBody); propertyList.forEach(function(key) < var headerCell = document.createElement("th"); tableHeaderRow.appendChild(headerCell); headerCell.textContent = key; >); items.forEach(function(foodItem) < var foodRow = document.createElement("tr"); tableBody.appendChild(foodRow); propertyList.forEach(function(propertyName) < var foodProperty = document.createElement("td"); foodRow.appendChild(foodProperty); if (propertyName === "imageSrc") < var image = document.createElement("img"); foodProperty.appendChild(image); image.src = foodItem[propertyName]; image.alt = foodItem[propertyName]; >else < foodProperty.textContent = foodItem[propertyName]; >>); >);
If you cannot merge the arrays then you can use this instead.
var item = ["Chicken soup", "Chicken tacos", "Chicken quesadilla", "Chicken burrito", "Chicken enchilada"]; var itemDescription = ["Delicious creamy chicken soup", "Homemade tacos", "Cheesy chicken quesadillas", "Hearty stuffed chicken burrito", "World famous chicken enchilada"]; var itemPrice = [14.99, 17.99, 15.75, 22.95, 12.55]; var imgArray = new Array(); imgArray[0] = new Image(); imgArray[0].src = 'chickensoup.jpg'; imgArray[1] = new Image(); imgArray[1].src = 'chickentaco.jpg'; imgArray[2] = new Image(); imgArray[2].src = 'chickenque.jpg'; imgArray[3] = new Image(); imgArray[3].src = 'chickenburrito.jpg'; imgArray[4] = new Image(); imgArray[4].src = 'chickenenchilada.jpg'; var foodList = < name: item, description: itemDescription, price: itemPrice, imageSrc: imgArray >; var propertyList = ["name", "description", "price", "imageSrc"]; var table = document.createElement("table"); var tableHeader = document.createElement("thead"); var tableHeaderRow = document.createElement("tr"); var tableBody = document.createElement("tbody"); table.setAttribute("border", "1"); document.body.appendChild(table); table.appendChild(tableHeader); tableHeader.appendChild(tableHeaderRow); table.appendChild(tableBody); propertyList.forEach(function(key) < var headerCell = document.createElement("th"); tableHeaderRow.appendChild(headerCell); headerCell.textContent = key; >); for (var index = 0; index < item.length; index++) < var foodRow = document.createElement("tr"); tableBody.appendChild(foodRow); propertyList.forEach(function(propertyName) < var foodProperty = document.createElement("td"); foodRow.appendChild(foodProperty); if (propertyName === "imageSrc") < foodProperty.appendChild(foodList[propertyName][index]); >else < foodProperty.textContent = foodList[propertyName][index]; >>); >
How to create a table using a loop?
The individual table rows are giving me a problem. I have created what I want using divs but I need to use a table instead of divs. My table has 220 cells, 10 rows, and 22 columns. Each cell has to have the value of i inside the innerHTML . Here is similar to what i want using Divs ( although the cell height and width does not have to be set ):
#container < width:682px; height:310px; background-color:#555; font-size:85%; >.cell
Use document.createElement() instead of innerHTML for dynamically inserting elements. innerHTML will remove any events attached to the child elements and will have to re-render every single row element all over again each time you parse it.
4 Answers 4
You can do this with nested loops — one to add cells to each row and one to add rows to the table. JSFiddle
var table = document.createElement('table'), tr, td, row, cell; for (row = 0; row < 10; row++) < tr = document.createElement('tr'); for (cell = 0; cell < 22; cell++) < td = document.createElement('td'); tr.appendChild(td); td.innerHTML = row * 22 + cell + 1; >table.appendChild(tr); > document.getElementById('container').appendChild(table);
Alternatively, you can create an empty row of 22 cells, clone it 10 times, and then add the numbers to the cells.
var table = document.createElement('table'), tr = document.createElement('tr'), cells, i; for (i = 0; i < 22; i++) < // Create an empty row tr.appendChild(document.createElement('td')); >for (i = 0; i < 10; i++) < // Add 10 copies of it to the table table.appendChild(tr.cloneNode(true)); >cells = table.getElementsByTagName('td'); // get all of the cells for (i = 0; i < 220; i++) < // number them cells[i].innerHTML = i + 1; >document.getElementById('container').appendChild(table);
And a third option: add the cells in a single loop, making a new row every 22 cells.
var table = document.createElement('table'), tr, td, i; for (i = 0; i < 220; i++) < if (i % 22 == 0) < // every 22nd cell (including the first) tr = table.appendChild(document.createElement('tr')); // add a new row >td = tr.appendChild(document.createElement('td')); td.innerHTML = i + 1; > document.getElementById('container').appendChild(table);
Edit — how I would do this nowadays (2021). with a helper function of some kind to build dom elements, and using map .
function make(tag, content) < const el = document.createElement(tag); content.forEach(c =>el.appendChild(c)); return el; > document.getElementById("container").appendChild(make( "table", [. Array(10).keys()].map(row => make( "tr", [. Array(22).keys()].map(column => make( "td", [document.createTextNode(row * 22 + column + 1)] )) )) ));
There are a lot of ways to do this, but one I’ve found to be helpful is to create a fragment then append everything into it. It’s fast and limits DOM re-paints/re-flows from a loop.
function newNode(node, text, styles) < node.innerHTML = text; node.className = styles; return node; >var fragment = document.createDocumentFragment(), container = document.getElementById("container"); for(var i = 1; i container.appendChild(fragment);
You can modify whatever you want inside the loop, but this should get you started.
That’s because the DOM magically wraps a element around stray table rows in your table, as it is designed to do. Fortunately, you can rewrite your loop in a way that will add all of those table rows at once, rather than one at a time.
The simplest solution to achieve this would be to store a string variable, and concatenate your rows onto that. Then, after you’ve concatenated your rows together into one string, you can set the innerHTML of your table element to that one string like so:
Here’s a JSFiddle that demonstrates what I’ve just written. If you inspect the HTML using your browser’s developer tools, you’ll notice that one (and only one) tbody wraps around all of your table rows.
Also, if you’re wondering, the odd-looking function which wraps around that code is simply a fancy way of keeping the variables you’ve created from becoming global (because they don’t need to be). See this blog post for more details on how that works.
HTML table to Loop Through each row
I have a HTML table which have a input field by default it is 0 initially, what I am doing is I am saving all the Items which have a value greater than 0, so it is working fine, but at UI end what i want to do is when user initially loads the page it shows up HTML table with one column having input field and values as 0 , so if user clicks on save without entering any value in input field then I am trying to prompt an alert quantity field value should be greater then 0 , but when I am doing this it is only checking for 1st row Code
var tableDataDraft = [ < "Code": "1248", "Item Name": "Tandoori Roti", "Selling Price": "45.0000", "Qty": "0" >, < "Code": "1249", "Item Name": "Naan-Plain", "Selling Price": "50.0000", "Qty": "0" >, < "Code": "1250", "Item Name": "Naan-Butter", "Selling Price": "60.0000", "Qty": "0" >, < "Code": "1251", "Item Name": "Naan-Garlic", "Selling Price": "55.0000", "Qty": "0" >, < "Code": "1252", "Item Name": "Kulcha-Plain", "Selling Price": "50.0000", "Qty": "0" >, < "Code": "1253", "Item Name": "Kulcha-Butter", "Selling Price": "60.0000", "Qty": "0" >, < "Code": "1254", "Item Name": "Kulcha-Amritsari", "Selling Price": "65.0000", "Qty": "0" >, < "Code": "1255", "Item Name": "Kulcha-Punjabi", "Selling Price": "60.0000", "Qty": "0" >, < "Code": "1256", "Item Name": "Kulcha-Jaipuar", "Selling Price": "60.0000", "Qty": "0" >, < "Code": "1257", "Item Name": "Paratha-Aloo", "Selling Price": "60.0000", "Qty": "0" >, < "Code": "1258", "Item Name": "Paratha-Methi", "Selling Price": "55.0000", "Qty": "0" >, < "Code": "1259", "Item Name": "Paratha-Pudina", "Selling Price": "60.0000", "Qty": "0" >, < "Code": "1260", "Item Name": "Paratha-Lacha", "Selling Price": "55.0000", "Qty": "0" >, < "Code": "603", "Item Name": "AMUL FRESH CREAM", "Selling Price": "134.8700", "Qty": "0" >] var itemsQuantiry1 = []; function addTableDraft(tableDataDraft) < var col = Object.keys(tableDataDraft[0]); var countNum = col.filter(i =>!isNaN(i)).length; var num = col.splice(0, countNum); col = col.concat(num); var table = document.createElement("table"); var tr = table.insertRow(-1); for (var i = 0; i < col.length; i++) < var th = document.createElement("th"); th.innerHTML = col[i]; tr.appendChild(th); tr.classList.add("text-center"); tr.classList.add("head") >for (var i = 0; i < tableDataDraft.length; i++) < tr = table.insertRow(-1); tr.classList.add("item-row"); for (var j = 0; j < col.length; j++) < var categoryName = tableDataDraft[i]["Category Name"]; tr.dataset.category = categoryName; let tabCell = tr.insertCell(-1); var hiddenField = document.createElement("input"); hiddenField.style.display = "none"; var tabledata = tableDataDraft[i][col[j]]; if (tableDataDraft[i]['Code'] === tableDataDraft[i][col[j]]) < tabCell.innerHTML = tabledata; hiddenField.setAttribute('name', 'Item_Code'); hiddenField.setAttribute('value', tabledata); tabCell.appendChild(hiddenField); >if (tableDataDraft[i]['Item Name'] === tableDataDraft[i][col[j]]) < tabCell.innerHTML = tabledata; hiddenField.setAttribute('name', 'Item_Name'); hiddenField.setAttribute('value', tabledata); tabCell.appendChild(hiddenField); >if (tableDataDraft[i]['Selling Price'] === tableDataDraft[i][col[j]]) < tabCell.innerHTML = tabledata; hiddenField.setAttribute('name', 'Selling_Price'); hiddenField.setAttribute('value', tabledata); tabCell.appendChild(hiddenField); >if (tableDataDraft[i]['Outlet Id'] === tableDataDraft[i][col[j]]) < tabCell.innerHTML = tabledata; hiddenField.setAttribute('name', 'Outlet_Id'); hiddenField.setAttribute('value', tabledata); tabCell.appendChild(hiddenField); >if (tableDataDraft[i]['Qty'] === tableDataDraft[i][col[j]]) < tabCell.classList.add("dheeraj") var quantityField = document.createElement("input"); quantityField.style.border = "none"; quantityField.style["text-align"] = "right"; quantityField.setAttribute("name", "Quantity_field"); quantityField.setAttribute("autocomplete", "on"); if (itemsQuantiry1[i]) < quantityField.setAttribute("value", itemsQuantiry1[i]); >else < quantityField.setAttribute("value", tabledata); >quantityField.setAttribute("index", i); quantityField.setAttribute("type", "number"); quantityField.setAttribute("min", "0"); quantityField.setAttribute("max", "999"); // quantityField.setAttribute("onfocus", "this.value=''"); quantityField.setAttribute("required", "required"); quantityField.classList.add("dataReset"); quantityField.toLocaleString('en-IN'); tabCell.appendChild(quantityField); > if (j > 1) tabCell.classList.add("text-right"); > > var divContainer = document.getElementById("indentTable"); divContainer.innerHTML = ""; divContainer.appendChild(table); table.classList.add("table"); table.classList.add("table-striped"); table.classList.add("table-bordered"); table.classList.add("table-hover"); > addTableDraft(tableDataDraft) $("#save").click(function() < var emptyQuantity = $(".dataReset").val(); //on click of save want to check quantity field should be greater then zero if (emptyQuantity === '0') < alert("Quantity field Value Should be greater then 0"); >>);
- If any Quantity field has value greater then 0 then i can allow user to save data,but if all the input fields have value 0 in each row then trying to prompt message
- Currently what it is doing it only checks 1st row if it has value greater then zero then it saves data otherwise prompt mesage
- So in case when user let 1st row data be zero and other data He/She entered any thing then it is checking only First Row
i have commented the Save button code in my snippet
Any kind of help or approach will be appreciated,Thankyou
How do I iterate through table rows and cells in JavaScript?
How would I iterate through all table rows (assuming the number of rows could change each time I check) and retrieve values from each cell in each row from within JavaScript?
15 Answers 15
var table = document.getElementById("mytab1"); for (var i = 0, row; row = table.rows[i]; i++) < //iterate through rows //rows would be accessed using the "row" variable assigned in the for loop for (var j = 0, col; col = row.cells[j]; j++) < //iterate through columns //columns would be accessed using the "col" variable assigned in the for loop >>
var table = document.getElementById("mytab1"); for (var i = 0, cell; cell = table.cells[i]; i++) < //iterate through cells //cells would be accessed using the "cell" variable assigned in the for loop >
@JohnHartsock I know but I used your solution and figured out that it does not work on IE. It is just a comment to warn the others. I voted up your answer anyway 😉
For those (coming here through google) needing a simple and small shim for table.cells (to patch up some older/IE-oriented code), see my answer to Q: Does Firefox browser not recognize table.cells?
You can consider using jQuery. With jQuery it’s super-easy and might look like this:
That’s a crazy policy. You could always just copy-n-paste the relevant functions you need from jQuery to your own application code. Unless there’s a policy against using other people’s code online, but then you wouldn’t be here.
Another reason to disallow JQuery is for embedded websites e.g. I’m using an embedded WiFi chip which only has 250Kb for the whole website. It’s a squeeze with all the images as it is.
for (let row of mytab1.rows) < for(let cell of row.cells) < let val = cell.innerText; // your code below >>
for (let row of mytab1.rows) < for(let cell of row.cells) < console.log(cell.innerText) >>
col1 Val1 col2 Val2 col1 Val3 col2 Val4
for ( let [i,row] of [. mytab1.rows].entries() ) < for( let [j,cell] of [. row.cells].entries() ) < console.log(`[$,$] = $`) > >
col1 Val1 col2 Val2 col1 Val3 col2 Val4
Notice the «for . of» in the loops. Would’ve been nice to have some explanation in your answer. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Elegant way to do the work without dom/jQuery. How could I finally get all inputs in the cell? (Or all inputs in a row)
var table=document.getElementById("mytab1"); var r=0; //start counting rows in table while(row=table.rows[r++]) < var c=0; //start counting columns in row while(cell=row.cells[c++]) < cell.innerHTML='[R'+r+'C'+c+']'; // do sth with cell >>
In each pass through while loop r/c iterator increases and new row/cell object from collection is assigned to row/cell variables. When there’s no more rows/cells in collection, false is assigned to row/cell variable and iteration through while loop stops (exits).
in previous post: while (cell=row[r].cells[c++] should be row.cells[c++], row being the current object, and an example for the sth code: mycoldata = cell.innerHTML
Better solution: use Javascript’s native Array.from() and to convert HTMLCollection object to an array, after which you can use standard array functions.
var t = document.getElementById('mytab1'); if(t) < Array.from(t.rows).forEach((tr, row_ind) => < Array.from(tr.cells).forEach((cell, col_ind) =>< console.log('Value at row/col [' + row_ind + ',' + col_ind + '] = ' + cell.textContent); >); >); >
You could also reference tr.rowIndex and cell.colIndex instead of using row_ind and col_ind .
I much prefer this approach over the top 2 highest-voted answers because it does not clutter your code with global variables i , j , row and col , and therefore it delivers clean, modular code that will not have any side effects (or raise lint / compiler warnings). without other libraries (e.g. jquery). Furthermore, it gives your code access to both element and index vars rather than just the element, and if you prefer to hide the index, you can just ignore it in the callback arg list.
If you require this to run in an old version (pre-ES2015) of Javascript, Array.from can be polyfilled.