简体   繁体   中英

Generating an HTML table from an array of objects

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.

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>

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>

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>

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.

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) 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM