What are the advantages and disadvantages of these methods of creating tables with JavaScript?

javascript

Solution

If you can avoid using the elements, and just put a string into an `innerHTML` you'll get the best performance. Here are some different ways to create a table.

Functional Code demo

We can create some functions to generate our HTML. This code will be very fast (but could be faster). We'll assume this data for all of these examples.

var heading = ['Name', 'Points'];

var data = [
  ["Joe", 50],
  ["Jack", 80],
  ["Doug <b>'the hammer'</b> Jones", 76]
];

We can then generate our table like so,

document.body.innerHTML = table(heading, data);
function wrapTag(tag, html) {
  return "<" + tag + ">" + html + "</" + tag + ">";
}


function table(head, body) {
    return wrapTag("table", thead(head)
    + tbody(body));
}

function thead(head) {
  var _th = head.map(wrapTag.bind(null, "th"));
  var _tr = wrapTag("tr", _th.join("\n"));
  return wrapTag("thead", _tr);
}

function tbody(body) {
  return body.map(tr).join("\n");
}

function tr(row) {
  var _td = row.map(wrapTag.bind(null, "td"));
  return wrapTag("tr", _td.join("\n"));
}

KnockoutJS demo

In Knockout we can give it an object, and have it map directly to our HTML. With the `heading` and `data` variables defined above, we map this like so.

ko.applyBindings({heading: heading, data: data});

Our HTML makes use of the `foreach` binding, which iterates over an array. `$data` refers to the current array item.

<table>
  <thead>
    <tr data-bind="foreach: heading">
      <th data-bind="text: $data"></th>
    </tr>
  </thead>
  <tbody data-bind="foreach: data">
    <tr data-bind="foreach: $data">
      <td data-bind="html: $data"></td>
    </tr>
  </tbody>
</table>

AngularJS demo

Using the same data from above, we can create an AngularJS controller.

function MyTableCtrl($scope) {
  $scope.heading = heading;
  $scope.data = data;
}

Our HTML is similar to KnockoutJS. One difference is the looping syntax, which lets us name our elements, e.g., `row in data`, instead of referring to elements as `$data`.

  <table ng-controller="MyTableCtrl">
    <thead>
      <tr>
        <th ng-repeat="head in heading">{{head}}</th>
      </tr>
    </thead>
    <tbody>
      <tr ng-repeat="row in data">
        <td ng-repeat="content in row" ng-bind-html-unsafe="content"></td>
      </tr>
    </tbody>
  </table>

documentFragment demo

credit to @Ian

This is faster than regular DOM manipulation, and provides a nicer syntax than combining strings.

newTable = createTable(heading, data);
document.body.appendChild(newTable);
function createTable(h, c) {
    var frag, table, head, body;

    frag = document.createDocumentFragment();
    table = document.createElement("table");
    head = createHeader(h);
    body = createContent(c);

    table.appendChild(head);
    table.appendChild(body);

    frag.appendChild(table);

    return frag.cloneNode(true);
}

function createHeader(data) {
    var thead, rowEl, col, colEl, text, i, j;

    thead = document.createElement("thead")
    rowEl = document.createElement("tr");

    for (i = 0, j = data.length; i < j; i++) {
        col = data[i];
        colEl = document.createElement("td");
        text = document.createTextNode(col);
        colEl.appendChild(text);
        rowEl.appendChild(colEl);
    }

    thead.appendChild(rowEl);

    return thead;
}

function createContent(data) {
    var content, row, rowEl, col, colEl, text, i, j, k, l;

    content = document.createElement("tbody");

    for (i = 0, j = data.length; i < j; i++) {
        row = data[i];
        rowEl = document.createElement("tr");
        for (k = 0, l = row.length; k < l; k++) {
            col = row[k];
            colEl = document.createElement("td");
            text = document.createTextNode(col);
            colEl.appendChild(text);
            rowEl.appendChild(colEl);
        }
        content.appendChild(rowEl);
    }

    return content;
}

Problem

I found two ways to create a table in JS: Using `insertRow` and `insertCell`: ``` var table = document.getElementById ("table"); var row = table.insertRow (1); var cell = row.insertCell (0); cell.innerHTML = "New row"; ``` Using plain DOM operations: ``` var tbl = document.createElement("table"); var tblBody = document.createElement("tbody"); // creating all cells for (var j = 0; j < 2; j++) { // creates a table row var row = document.createElement("tr"); for (var i = 0; i < 2; i++) { // Create a <td> element and a text node, make the text // node the contents of the <td>, and put the <td> at // the end of the table row var cell = document.createElement("td"); var cellText = document.createTextNode("cell is row "+j+", column "+i); cell.appendChild(cellText); row.appendChild(cell); } // add the row to the end of the table body tblBody.appendChild(row); } ``` The first as I see is specially created for the table, but the second is mentioned on MDN, so I'm a bit confused what methods to use. What are the advantages and disadvantages of each? When is one used over another?

Original source

Related problems