HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Output JavaScript object into HTML table of key-value pairs using jQuery

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
javascriptintotableoutputvaluejqueryusingobjectpairshtml

Problem

This function is meant to take an object, loop through the key-values and generate/build a HTML table at a particular ID:

function insertBasicTable(basic_data, insert_id) {
  /* Insert the key/value pairs into a table element on the DOM.

  basic_data = object containing key/value pairs
  insert_id  = the id on the DOM to insert the table into 

  Intentionally not including closing tags in the jquery requests;
  http://stackoverflow.com/a/14737115/2355035 */

  table_id = '#' + insert_id;
  var array_length = Object.keys(basic_data).length;
  var array_obj_names = Object.keys(basic_data);

  // create the table header
  $(table_id).empty();
  $(table_id).append('');
  $(table_id).find('thead:last').append('Tag');
  $(table_id).find('thead:last').append('Data');

  // begin the table body and iterate through key/value pairs
  $(table_id).append('');
  for (var i = 0; i ' + array_obj_names[i];
    var data      = '' + basic_data[attr_name];

    $(table_id).find('tbody:last').append('' + tag + data);
  }
}


This function is then used, along with a number of D3 scripts, to populate elements on the DOM:

linePlot.render(someObject.modules.qual.quintiles);
boxPlot.render(someObject.modules.qual.quintiles);
insertBasicTable(someObject.modules.basic, 'basic-stats-table');
// etc, etc...


Any comments about how this is being achieved? Am I overlooking either a basic tenant of how JS "should" be used (this is a huge side-effect for instance, should I be returning a formatted string then placing that string into the DOM for instance) or over-complicating things by jQuery'ing a bunch of times?

Solution

Let's start with your version:

1) Unnecessary optimization.

var array_length = Object.keys(basic_data).length;
var array_obj_names = Object.keys(basic_data);


This gives you nothing in terms of performance. It would be optimized away by the browser.

2) Chain-calling

$(table_id).empty();
$(table_id).append('');


It is possible to do chain-calls like: $('#elem').doA().doB().doC()

3) Misunderstanding calls

$(table_id).find('thead:last').append('Tag');


.append() does exactly that: appending after the last element.

4) NuStyleLoopz

for (var i = 0; i ' + array_obj_names[i];
    var data      = '' + basic_data[attr_name];


You could iterate over the keys directly via Object.keys() with

-
Array.prototype.forEach()

-
Array.prototype.map()

-
Array.protoype.reduce() / Array.prototype.reduceRight().

Here a slighty pimped version:

makeTag=function(openTag, closeTag){
            return function(content){
                return openTag+content+closeTag;  
            };
        };
tHead=makeTag("","");
tBody=makeTag("","");
td=makeTag("","");
tr=makeTag("","");

function insertBasicTable(data,id){
    $('#'+id).html(
        tHead(
            tr(
                td("Tag")+
                td("Data")
            )
        )+
        tBody(
            Object.keys(data).reduce(function(o,n){
                return o+tr(
                    td(n)+""+
                    td(data[n]+"")
                );
            },"")
        )
    );
};

insertBasicTable({"key1":"value1","key2":"value2"},"mytable");


Here is the fiddle to play with.

To make HTML-generation less painfull and a bit more JS-stylish I define what is called a higher order function makeTag: simply a function returning a function. A call to var tHead=makeTag("",""); generates an anonymous function (a function without name), which returns every time it's called "`"+ parameter +"". The same goes for the other tags. This allows me to do something like a DSL:

tHead(
        tr(
            td("Tag")+
            td("Data")
        )
    )


That is not only handy, but cool B-)
Besides it is nearly as readable as
html` and not so noisy like the typical string concatenation and the risk of typos is really low.

Code Snippets

var array_length = Object.keys(basic_data).length;
var array_obj_names = Object.keys(basic_data);
$(table_id).empty();
$(table_id).append('<thead>');
$(table_id).find('thead:last').append('<th>Tag');
for (var i = 0; i < array_length; i++) {
    var attr_name = array_obj_names[i];
    var tag       = '<td>' + array_obj_names[i];
    var data      = '<td>' + basic_data[attr_name];
makeTag=function(openTag, closeTag){
            return function(content){
                return openTag+content+closeTag;  
            };
        };
tHead=makeTag("<thead>","</thead>");
tBody=makeTag("<tbody>","</tbody>");
td=makeTag("<td>","</td>");
tr=makeTag("<tr>","</tr>");

function insertBasicTable(data,id){
    $('#'+id).html(
        tHead(
            tr(
                td("Tag")+
                td("Data")
            )
        )+
        tBody(
            Object.keys(data).reduce(function(o,n){
                return o+tr(
                    td(n)+""+
                    td(data[n]+"")
                );
            },"")
        )
    );
};

insertBasicTable({"key1":"value1","key2":"value2"},"mytable");

Context

StackExchange Code Review Q#77286, answer score: 7

Revisions (0)

No revisions yet.