0

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.

  • 1
    `units[n][m]` could you please tell us what is `n` & `m` here and what did you expect it would return? – palaѕн Apr 10 '20 at 14:04
  • 2
    How is it you've "tried a function" but have no idea how it works? What's the question, exactly? Are you familiar with JavaScript debugging? You should be able to set breakpoints in your code and see what's happening. – isherwood Apr 10 '20 at 14:05
  • 1
    @isherwood in particular asks good questions. It's also not clear what 'get a query into the function' means, so if you could explain that, that'd help. –  Apr 10 '20 at 14:16
  • Does this answer your question? [Parsing JSON objects for HTML table](https://stackoverflow.com/questions/17066636/parsing-json-objects-for-html-table) – Heretic Monkey Apr 10 '20 at 14:32

5 Answers5

2

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>
M A Salman
  • 3,666
  • 2
  • 12
  • 26
1

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>
DCR
  • 14,737
  • 12
  • 52
  • 115
0

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>
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
0

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.

Community
  • 1
  • 1
Tom O.
  • 5,730
  • 2
  • 21
  • 35
0

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) 
Youcef Ali
  • 189
  • 1
  • 6