Reputation: 1
I've been trying to generate a function to create an HTML table from an array of objects. This is the array that needs to be made into a table.
let units = [
{
'code': 'COMP2110',
'title': 'Web Technology',
'offering': 'S1'
},
{
'code': 'COMP2010',
'title': 'Algorithms and Data Structures',
'offering': 'S1'
},
{
'code': 'COMP2150',
'title': 'Game Design',
'offering': 'S1'
},
{
'code': 'COMP2320',
'title': 'Offensive Security',
'offering': 'S1'
},
{
'code': 'COMP2200',
'title': 'Data Science',
'offering': 'S2'
},
{
'code': 'COMP2250',
'title': 'Data Communications',
'offering': 'S2'
},
{
'code': 'COMP2300',
'title': 'Applied Cryptography',
'offering': 'S2'
},
{
'code': 'COMP2000',
'title': 'Object-Oriented Programming Practices',
'offering': 'S2'
},
{
'code': 'COMP2050',
'title': 'Software Engineering',
'offering': 'S2'
},
{
'code': 'COMP2100',
'title': 'Systems Programming',
'offering': 'S2'
}
]
I've tried a function but I have no idea how to get it to work. I also have no idea how to get a query into the function.
function unit_table() {
var totalRows = 3;
var cellsInRow = 3;
function drawTable() {
// get the reference for the body
var first = document.getElementById('first');
// creates a <table> element
var tbl = document.createElement("table");
// creating rows
for (var r = 0; r < totalRows; r++) {
var row = document.createElement("tr");
// create cells in row
for (var c = 0; c < cellsInRow; c++) {
m=0;
var cell = document.createElement("td");
var cellText = document.createTextNode(units[n][m]);
cell.appendChild(cellText);
row.appendChild(cell);
m=m+1;
}
n=n+1;
tbl.appendChild(row); // add the row to the end of the table body
}
first.appendChild(tbl); // appends <table> into <first>
}
window.onload=drawTable;
// your code here
}
Any help would be greatly appreciated.
Upvotes: 0
Views: 1974
Reputation: 309
Example Arry of Object
let cars = [
{
"color": "purple",
"type": "minivan",
"registration": new Date('2017-01-03'),
"capacity": 7
},
{
"color": "red",
"type": "station wagon",
"registration": new Date('2018-03-03'),
"capacity": 5
}]
The Function :
function ArrayToHtmlTable(htmlelement,ArrayObject) {
TableHeader = Object.keys(ArrayObject[0])
.map((x) => "<th>" + x + "</th>")
.join("");
TableBody = ArrayObject.map(
(x) =>
"<tr>" +
Object.values(x)
.map((x) => "<td>" + x + "</td>")
.join() +
"<tr>"
).join("");
document.getElementById(
htmlelement
).innerHTML += `<table> ${TableHeader} ${TableBody}</table>`;
}
Function Call :
ArrayToHtmlTable("testTable",cars)
Upvotes: 0
Reputation: 5941
You could achieve this pretty easily by taking advantage of the DOM API and Array.prototype.reduce
method - for example:
const units = [{
'code': 'COMP2110',
'title': 'Web Technology',
'offering': 'S1'
},
{
'code': 'COMP2010',
'title': 'Algorithms and Data Structures',
'offering': 'S1'
},
{
'code': 'COMP2150',
'title': 'Game Design',
'offering': 'S1'
},
{
'code': 'COMP2320',
'title': 'Offensive Security',
'offering': 'S1'
},
{
'code': 'COMP2200',
'title': 'Data Science',
'offering': 'S2'
},
{
'code': 'COMP2250',
'title': 'Data Communications',
'offering': 'S2'
},
{
'code': 'COMP2300',
'title': 'Applied Cryptography',
'offering': 'S2'
},
{
'code': 'COMP2000',
'title': 'Object-Oriented Programming Practices',
'offering': 'S2'
},
{
'code': 'COMP2050',
'title': 'Software Engineering',
'offering': 'S2'
},
{
'code': 'COMP2100',
'title': 'Systems Programming',
'offering': 'S2'
}
];
const createEmptyTable = () => {
const tableEl = document.createElement('table');
tableEl.appendChild(document.createElement('thead'));
tableEl.appendChild(document.createElement('tbody'));
return tableEl;
};
const createTableHeadersRow = data => {
const fields = Object.keys(data);
return fields.reduce((trEl, fieldName) => {
const tdEl = document.createElement('th');
tdEl.appendChild(document.createTextNode(fieldName));
trEl.appendChild(tdEl);
return trEl;
}, document.createElement('tr'));
};
const createTableBodyRow = data => {
const values = Object.values(data);
return values.reduce((trEl, value) => {
const tdEl = document.createElement('td');
tdEl.appendChild(document.createTextNode(value));
trEl.appendChild(tdEl);
return trEl;
}, document.createElement('tr'));
};
const createUnitTable = unitsArray => {
return unitsArray.reduce((tableEl, unit, idx) => {
const tableNeedsHeaderRow = idx === 0;
if (tableNeedsHeaderRow) {
tableEl.querySelector('thead').appendChild(createTableHeadersRow(unit));
}
tableEl.querySelector('tbody').appendChild(createTableBodyRow(unit));
return tableEl;
}, createEmptyTable());
};
document.querySelector('div').appendChild(createUnitTable(units));
td {
padding: .5rem;
border: 1px solid black;
}
th {
text-transform: capitalize
}
<div></div>
I personally find breaking code up into smaller functions, each with a single responsibility (and descriptive name), makes it way easier to read and comprehend. This is why I broke this task up into 4 small functions instead of one one behemoth function to do the job.
Upvotes: 0
Reputation: 3820
The units[n][m]
will work if m
is a string containing the key of the object.
example units[0]["code"]
will return the code value of first object.
Populating the table can be done by making html dynamically in string and table.innerHTML
to set it to table.
For this purpose we iterate through keys using for (let key in object)
For column names
let tableString="<tr>"
for(let column in units[0]){
tableString+=`<th>${column}</th>`
}
Above code will make a string like this
<tr>
<th>code</th>
<th>title</th>
<th>offering</th>
</tr>
For column data
tableString+="</tr>"
units.forEach(element => {
tableString+="<tr>"
for(let prop in element){
tableString+=`<td>${element[prop]}</td>`
}
tableString+="</tr>"
});
Above will make string like this and this will repeat until end of array
<tr>
<td>COMP2110</td>
<td>Web Technology</td>
<td>S1</td>
</tr>
<tr>...
</tr>
<tr>...
</tr>
and finally
document.querySelector('#tb').innerHTML=tableString;
let units = [
{
'code': 'COMP2110',
'title': 'Web Technology',
'offering': 'S1'
},
{
'code': 'COMP2010',
'title': 'Algorithms and Data Structures',
'offering': 'S1'
},
{
'code': 'COMP2150',
'title': 'Game Design',
'offering': 'S1'
},
{
'code': 'COMP2320',
'title': 'Offensive Security',
'offering': 'S1'
},
{
'code': 'COMP2200',
'title': 'Data Science',
'offering': 'S2'
},
{
'code': 'COMP2250',
'title': 'Data Communications',
'offering': 'S2'
},
{
'code': 'COMP2300',
'title': 'Applied Cryptography',
'offering': 'S2'
},
{
'code': 'COMP2000',
'title': 'Object-Oriented Programming Practices',
'offering': 'S2'
},
{
'code': 'COMP2050',
'title': 'Software Engineering',
'offering': 'S2'
},
{
'code': 'COMP2100',
'title': 'Systems Programming',
'offering': 'S2'
}
]
let tableString="<tr>"
for(let column in units[0]){
tableString+=`<th>${column}</th>`
}
tableString+="</tr>"
units.forEach(element => {
tableString+="<tr>"
for(let prop in element){
tableString+=`<td>${element[prop]}</td>`
}
tableString+="</tr>"
});
document.querySelector('#tb').innerHTML=tableString;
table td {
border:1px solid black;
}
<table id="tb">
</table>
Upvotes: 2
Reputation: 48743
That is not a multi-dimensions array. That is an array of object records...
With a function like populateTableWithJSON
, you can generate or fill a table with a list of JSON objects.
const main = () => {
let table = document.querySelector('#units')
let units = getUnits()
populateTableWithJSON(units, table)
}
/**
* @return Returns the table that was passed in,
* or a new table, if null
*/
const populateTableWithJSON = (jsonData, table) => {
table = table || document.createElement('TABLE')
let thead = table.querySelector('thead')
if (thead == null) table.appendChild(createEl('THEAD'))
let tbody = table.querySelector('tbody')
if (tbody == null) table.appendChild(createEl('TBODY'))
emptyElement(tbody)
if (jsonData != null && jsonData.length > 0) {
let headers = thead.querySelectorAll('tr th'), fields = []
if (headers.length) {
fields = Array.from(headers).map(th => th.textContent);
} else {
fields = Object.keys(jsonData[0])
thead.appendChild(createEl('TR', null, null, ...fields.map(field => {
return createEl('TH', { textContent : field })
})))
}
appendAll(tbody, ...jsonData.map(record => {
return createEl('TR', null, null, ...fields.map(field => {
return createEl('TD', { textContent : record[field] })
}))
}))
}
return table
}
const createEl = (tag, props, attrs, ...children) => {
let el = document.createElement(tag)
Object.keys(props || {}).forEach(prop => el[prop] = props[prop])
Object.keys(attrs || {}).forEach(attr => el.setAttribute(attr, attrs[attr]))
return appendAll(el, ...children)
}
const appendAll = (el, ...children) => {
children.forEach(child => el.appendChild(child))
return el
}
const emptyElement = (element) => {
while (element.firstChild) element.removeChild(element.firstChild)
}
const getUnits = () => [{
'code': 'COMP2110',
'title': 'Web Technology',
'offering': 'S1'
}, {
'code': 'COMP2010',
'title': 'Algorithms and Data Structures',
'offering': 'S1'
}, {
'code': 'COMP2150',
'title': 'Game Design',
'offering': 'S1'
}, {
'code': 'COMP2320',
'title': 'Offensive Security',
'offering': 'S1'
}, {
'code': 'COMP2200',
'title': 'Data Science',
'offering': 'S2'
}, {
'code': 'COMP2250',
'title': 'Data Communications',
'offering': 'S2'
}, {
'code': 'COMP2300',
'title': 'Applied Cryptography',
'offering': 'S2'
}, {
'code': 'COMP2000',
'title': 'Object-Oriented Programming Practices',
'offering': 'S2'
}, {
'code': 'COMP2050',
'title': 'Software Engineering',
'offering': 'S2'
}, {
'code': 'COMP2100',
'title': 'Systems Programming',
'offering': 'S2'
}]
main()
table, th, td {
border: thin solid grey;
}
table {
border-collapse: collapse;
}
th, td {
padding: 0.5em;
}
th {
text-transform: capitalize;
}
<table id="units">
<thead></thead>
<tbody></tbody>
</table>
Upvotes: 0
Reputation: 15700
your code was basically correct but you had some structural problems. you define functions inside of functions which cause some issues, you don't declare all variables an you're not accessing units correctly. Take a look and let me know if you need more help.
let units = [
{
'code': 'COMP2110',
'title': 'Web Technology',
'offering': 'S1'
},
{
'code': 'COMP2010',
'title': 'Algorithms and Data Structures',
'offering': 'S1'
},
{
'code': 'COMP2150',
'title': 'Game Design',
'offering': 'S1'
},
{
'code': 'COMP2320',
'title': 'Offensive Security',
'offering': 'S1'
},
{
'code': 'COMP2200',
'title': 'Data Science',
'offering': 'S2'
},
{
'code': 'COMP2250',
'title': 'Data Communications',
'offering': 'S2'
},
{
'code': 'COMP2300',
'title': 'Applied Cryptography',
'offering': 'S2'
},
{
'code': 'COMP2000',
'title': 'Object-Oriented Programming Practices',
'offering': 'S2'
},
{
'code': 'COMP2050',
'title': 'Software Engineering',
'offering': 'S2'
},
{
'code': 'COMP2100',
'title': 'Systems Programming',
'offering': 'S2'
}
]
key=['code','title','offering'];
console.log(units[1].title);
var totalRows = 3;
var cellsInRow = 3;
var n=0,m=0;
function drawTable() {
console.log('draw');
// get the reference for the body
var first = document.getElementById('first');
// creates a <table> element
var tbl = document.createElement("table");
// creating rows
for (var r = 0; r < totalRows; r++) {
var row = document.createElement("tr");
// create cells in row
m=0;
for (var c = 0; c < cellsInRow; c++) {
var cell = document.createElement("td");
var cellText = document.createTextNode(units[n][key[m]]);
cell.appendChild(cellText);
row.appendChild(cell);
m=m+1;
}
n=n+1;
console.log(row);
tbl.appendChild(row); // add the row to the end of the table body
}
first.appendChild(tbl); // appends <table> into <first>
}
// your code here
window.onload=drawTable();
<div id='first'></div>
Upvotes: 1