Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generate table from Object data

Tags:

javascript

dom

I have an object like the one below:

var obj = {
   a : {
      x : 1,
      y : 2,
      z : 3
   },
   b : {
      x : 1,
      y : 2,
      z : 3
   }
}

With it, I will like to generate the following table. Format is showed bellow

http://jsfiddle.net/gD87t/

I am trying to get the elements from object and and trying to append but getting confused with the rowSpan value

var tr = document.createElement('tr');
for(var i in obj){
   var td = document.createElement('td');
   td.rowSpan = ? // Here I am getting confused.
}

Can a template engine solve my problem? What is the best way to do this?

like image 328
Exception Avatar asked Dec 20 '22 04:12

Exception


2 Answers

Here's one way of doing it with a recursive function in pure js:

function addObjectToTable(table, obj, tr) {
  var rows = 0;
  for (key in obj) {
    if (tr == null) {
      tr = document.createElement('tr');
      table.appendChild(tr);
    }  

    var td = document.createElement('td');
    td.textContent = key;
    tr.appendChild(td);

    var value = obj[key];
    if (typeof value != 'object') {
      var td = document.createElement('td');
      td.textContent = value;
      tr.appendChild(td);
      rows += 1;
    }
    else {
      var subrows = addObjectToTable(table, value, tr);
      td.setAttribute('rowspan',subrows);
      rows += subrows;
    }

    tr = null;
  }
  return rows;
}

Which would be called like this:

var table = document.createElement('table');
addObjectToTable(table,obj);
document.body.appendChild(table);

Note that when first called, the tr parameter is null, since we always have to create a new row at the top level. When the function is called recursively though, the tr parameter is passed in from the upper level since lower levels will intially be adding to the the row of their parent object.

The function returns the number of rows added, so when it is called recusively the caller will know what to set the rowspan value to.

Fiddle link

like image 67
James Holderness Avatar answered Jan 10 '23 07:01

James Holderness


I couldn't find an answer which handled circulars, and I also decided to do this without any unnecessary DOM writes. Also, I didn't follow the exact mark-up the OP requested because I felt nesting tables was more convenient for a recursive operation such as this- and serves close to the same visual purpose.

So, here's the function I've created:

function dataToTable (data) {
    var storage = [];
    return (function buildTable (data) {
        var table = '<table><tbody>';
        var name, value;
        // Add the object/array to storage for cirular detection.
        storage.push(data);
        for (name in data) {
            value = data[name];
            table += '<tr><td>' + name + '</td><td>';
            // If the value is an object we've put in storage (circular)
            if (storage.indexOf(value) !== -1) {
                table += '<em>Circular</em>';
            } else if (typeof value === 'object') {
                table += buildTable(value);
            } else {
                table += value;
            }
            table += '</td></tr>';
        }
        return table + '</tbody></table>';
    }(data));
}

Here is the object I used to test:

var obj = {
   a : {
      x : 1,
      y : 2,
      z : 3
   },
   b : {
      x : 1,
      y : 2,
       z : {
           test1: 0,
           test2: {
               test3: 1,
               test4: ['a','b','c']
           }
       }
   }
};
obj.c = obj;
obj.b.z.test2.test4.push(obj.a);

The function will turn this object into an HTML table. What you do with the table is up to you. On my fiddle, I used the DOM to add the table to a DIV (document.getElementById).

http://jsfiddle.net/5RhXF/1/

I hope you'll find my implementation clear.

UPDATE::

I decided to test this on the jQuery library, and it worked! Except, the functions were printing as their toString value with no good format for text.. Which makes sense, but not very helpful. So, I'm thinking this is a nice and easy way to look through APIs for frameworks/libraries and what-not. Therefore, I added prettify for syntax-highlighting of functions, and also added a type-check for functions in the table generator, and a quick class to get rid of borders around the prettify box (as there's already a border on the table cell). If anyone is interested in the version designed for source-reading/debugging, here's the fiddle:

http://jsfiddle.net/5RhXF/7/

like image 42
Spencer Lockhart Avatar answered Jan 10 '23 09:01

Spencer Lockhart