[javascript] Dynamic creation of table with DOM

Can someone tell me what's wrong with this code? I want to create a table with 2 columns and 3 rows, and in the cells I want Text1 and Text2 on every row. This code creates a table with 2 columns and 3 rows, but it's only text in the cells in the third row (the others are empty).

var tablearea = document.getElementById('tablearea');

var table = document.createElement('table');

var tr = [];

var td1 = document.createElement('td');
var td2 = document.createElement('td');

var text1 = document.createTextNode('Text1');
var text2 = document.createTextNode('Text2');

for (var i = 1; i < 4; i++){
    tr[i] = document.createElement('tr');   
    for (var j = 1; j < 4; j++){
        td1.appendChild(text1);
        td2.appendChild(text2);
        tr[i].appendChild(td1);
        tr[i].appendChild(td2);
    }           
    table.appendChild(tr[i]);

}

tablearea.appendChild(table);

This question is related to javascript dom

The answer is


<title>Registration Form</title>
<script>
    var table;

    function check() {
        debugger;
        var name = document.myForm.name.value;
        if (name == "" || name == null) {
            document.getElementById("span1").innerHTML = "Please enter the Name";
            document.myform.name.focus();
            document.getElementById("name").style.border = "2px solid red";
            return false;
        }
        else {
            document.getElementById("span1").innerHTML = "";
            document.getElementById("name").style.border = "2px solid green";
        }

        var age = document.myForm.age.value;
        var ageFormat = /^(([1][8-9])|([2-5][0-9])|(6[0]))$/gm;

        if (age == "" || age == null) {
            document.getElementById("span2").innerHTML = "Please provide Age";
            document.myForm.age.focus();
            document.getElementById("age").style.border = "2px solid red";
            return false;
        }
        else if (!ageFormat.test(age)) {
            document.getElementById("span2").innerHTML = "Age can't be leass than 18 and greater than 60";
            document.myForm.age.focus();
            document.getElementById("age").style.border = "2px solid red";
            return false;
        }
        else {
            document.getElementById("span2").innerHTML = "";
            document.getElementById("age").style.border = "2px solid green";
        }

        var password = document.myForm.password.value;
        if (document.myForm.password.length < 6) {
            alert("Error: Password must contain at least six characters!");
            document.myForm.password.focus();
            document.getElementById("password").style.border = "2px solid red";
            return false;
        }
        re = /[0-9]/g;
        if (!re.test(password)) {
            alert("Error: password must contain at least one number (0-9)!");
            document.myForm.password.focus();
            document.getElementById("password").style.border = "2px solid red";
            return false;
        }
        re = /[a-z]/g;
        if (!re.test(password)) {
            alert("Error: password must contain at least one lowercase letter (a-z)!");
            document.myForm.password.focus();
            document.getElementById("password").style.border = "2px solid red";
            return false;
        }
        re = /[A-Z]/g;
        if (!re.test(password)) {
            alert("Error: password must contain at least one uppercase letter (A-Z)!");
            document.myForm.password.focus();
            document.getElementById("password").style.border = "2px solid red";
            return false;
        }
        re = /[$&+,:;=?@#|'<>.^*()%!-]/g;
        if (!re.test(password)) {
            alert("Error: password must contain at least one special character!");
            document.myForm.password.focus();
            document.getElementById("password").style.border = "2px solid red";
            return false;
        }
        else {
            document.getElementById("span3").innerHTML = "";
            document.getElementById("password").style.border = "2px solid green";

        }

        if (document.getElementById("data") == null)
            createTable();
        else {
            appendRow();
        }
        return true;
    }






    function createTable() {

        var myTableDiv = document.getElementById("myTable");  //indiv
        table = document.createElement("TABLE");   //TABLE??
        table.setAttribute("id", "data");
        table.border = '1';
        myTableDiv.appendChild(table);  //appendChild() insert it in the document (table --> myTableDiv)
        debugger;

        var header = table.createTHead();

        var th0 = table.tHead.appendChild(document.createElement("th"));
        th0.innerHTML = "Name";
        var th1 = table.tHead.appendChild(document.createElement("th"));
        th1.innerHTML = "Age";


        appendRow();

    }

    function appendRow() {
        var name = document.myForm.name.value;
        var age = document.myForm.age.value;


        var rowCount = table.rows.length;
        var row = table.insertRow(rowCount);

        row.insertCell(0).innerHTML = name;
        row.insertCell(1).innerHTML = age;



        clearForm();


    }


    function clearForm() {
        debugger;

        document.myForm.name.value = "";
        document.myForm.password.value = "";
        document.myForm.age.value = "";



    }
    function restrictCharacters(evt) {

        evt = (evt) ? evt : window.event;
        var charCode = (evt.which) ? evt.which : evt.keyCode;
        if (((charCode >= '65') && (charCode <= '90')) || ((charCode >= '97') && (charCode <= '122')) || (charCode == '32')) {
            return true;
        }
        else {
            return false;
        }
    }

</script>



<div>
    <form name="myForm">

        <table id="tableid">

            <tr>
                <th>Name</th>
                <td>
                    <input type="text" name="name" placeholder="Name" id="name" onkeypress="return restrictCharacters(event);" /></td>
                <td><span id="span1"></span></td>
            </tr>

            <tr>
                <th>Age</th>

                <td>
                    <input type="text" onkeypress="return event.charCode === 0 || /\d/.test(String.fromCharCode(event.charCode));" placeholder="Age"
                        name="age" id="age" /></td>
                <td><span id="span2"></span></td>
            </tr>

            <tr>
                <th>Password</th>
                <td>
                    <input type="password" name="password" id="password" placeholder="Password" /></td>
                <td><span id="span3"></span></td>
            </tr>


            <tr>
                <td></td>
                <td>
                    <input type="button" value="Submit" onclick="check();" /></td>
                <td>
                    <input type="reset" name="Reset" /></td>
            </tr>

        </table>
    </form>

    <div id="myTable">
    </div>

</div>

when you say 'appendchild' you actually move your child from one parent to another. you have to create a node for each cell.


It is because you're only creating two td elements and 2 text nodes.


Creating all nodes in a loop

Recreate the nodes inside your loop:

var tablearea = document.getElementById('tablearea'),
    table = document.createElement('table');

for (var i = 1; i < 4; i++) {
    var tr = document.createElement('tr');

    tr.appendChild( document.createElement('td') );
    tr.appendChild( document.createElement('td') );

    tr.cells[0].appendChild( document.createTextNode('Text1') )
    tr.cells[1].appendChild( document.createTextNode('Text2') );

    table.appendChild(tr);
}

tablearea.appendChild(table);

Creating then cloning in a loop

Create them beforehand, and clone them inside the loop:

var tablearea = document.getElementById('tablearea'),
    table = document.createElement('table'),
    tr = document.createElement('tr');

tr.appendChild( document.createElement('td') );
tr.appendChild( document.createElement('td') );

tr.cells[0].appendChild( document.createTextNode('Text1') )
tr.cells[1].appendChild( document.createTextNode('Text2') );

for (var i = 1; i < 4; i++) {
    table.appendChild(tr.cloneNode( true ));
}

tablearea.appendChild(table);

Table factory with text string

Make a table factory:

function populateTable(table, rows, cells, content) {
    if (!table) table = document.createElement('table');
    for (var i = 0; i < rows; ++i) {
        var row = document.createElement('tr');
        for (var j = 0; j < cells; ++j) {
            row.appendChild(document.createElement('td'));
            row.cells[j].appendChild(document.createTextNode(content + (j + 1)));
        }
        table.appendChild(row);
    }
    return table;
}

And use it like this:

document.getElementById('tablearea')
        .appendChild( populateTable(null, 3, 2, "Text") );

Table factory with text string or callback

The factory could easily be modified to accept a function as well for the fourth argument in order to populate the content of each cell in a more dynamic manner.

function populateTable(table, rows, cells, content) {
    var is_func = (typeof content === 'function');
    if (!table) table = document.createElement('table');
    for (var i = 0; i < rows; ++i) {
        var row = document.createElement('tr');
        for (var j = 0; j < cells; ++j) {
            row.appendChild(document.createElement('td'));
            var text = !is_func ? (content + '') : content(table, i, j);
            row.cells[j].appendChild(document.createTextNode(text));
        }
        table.appendChild(row);
    }
    return table;
}

Used like this:

document.getElementById('tablearea')
        .appendChild(populateTable(null, 3, 2, function(t, r, c) {
                        return ' row: ' + r + ', cell: ' + c;
                     })
        );

var html = "";
    for (var i = 0; i < data.length; i++){
    html +="<tr>"+
            "<td>"+ (i+1) + "</td>"+
            "<td>"+ data[i].name + "</td>"+
            "<td>"+ data[i].number + "</td>"+
            "<td>"+ data[i].city + "</td>"+
            "<td>"+ data[i].hobby + "</td>"+
            "<td>"+ data[i].birthdate + "</td>"+"<td><button data-arrayIndex='"+ i +"' onclick='editData(this)'>Edit</button><button data-arrayIndex='"+ i +"' onclick='deleteData()'>Delete</button></td>"+"</tr>";
}
$("#tableHtml").html(html);

You can create a dynamic table rows as below:

var tbl = document.createElement('table');
tbl.style.width = '100%';

for (var i = 0; i < files.length; i++) {

        tr = document.createElement('tr');

        var td1 = document.createElement('td');
        var td2 = document.createElement('td');
        var td3 = document.createElement('td');

        ::::: // As many <td> you want

        td1.appendChild(document.createTextNode());
        td2.appendChild(document.createTextNode());
        td3.appendChild(document.createTextNode();

        tr.appendChild(td1);
        tr.appendChild(td2);
        tr.appendChild(td3);

        tbl.appendChild(tr);
}

You need to create new TextNodes as well as td nodes for each column, not reuse them among all of the columns as your code is doing.

Edit: Revise your code like so:

for (var i = 1; i < 4; i++)
{
   tr[i] = document.createElement('tr');   
      var td1 = document.createElement('td');
      var td2 = document.createElement('td');
      td1.appendChild(document.createTextNode('Text1'));
      td2.appendChild(document.createTextNode('Text2'));
      tr[i].appendChild(td1);
      tr[i].appendChild(td2);
  table.appendChild(tr[i]);
}

In My example call add function from button click event and then get value from form control's and call function generateTable.
In generateTable Function check first Table is Generaed or not. If table is undefined then call generateHeader Funtion and Generate Header and then call addToRow function for adding new row in table.

<input type="button" class="custom-rounded-bttn bttn-save" value="Add" id="btnAdd" onclick="add()">


<div class="row">
    <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
        <div class="dataGridForItem">
        </div>
    </div>
</div>

//Call Function From Button click Event

var counts = 1;
function add(){ 
    var Weightage = $('#Weightage').val();
    var ItemName = $('#ItemName option:selected').text();  
    var ItemNamenum = $('#ItemName').val();
    generateTable(Weightage,ItemName,ItemNamenum);
     $('#Weightage').val('');
     $('#ItemName').val(-1);
     return true;
 } 


function generateTable(Weightage,ItemName,ItemNamenum){
    var tableHtml = '';
    if($("#rDataTable").html() == undefined){
        tableHtml = generateHeader();
    }else{
        tableHtml = $("#rDataTable");
    } 
    var temp = $("<div/>");
    var row = addToRow(Weightage,ItemName,ItemNamenum);
    $(temp).append($(row));
    $("#dataGridForItem").html($(tableHtml).append($(temp).html()));
}


//Generate Header


function generateHeader(){
        var html = "<table id='rDataTable' class='table table-striped'>";
        html+="<tr class=''>";
        html+="<td class='tb-heading ui-state-default'>"+'Sr.No'+"</td>";
        html+="<td class='tb-heading ui-state-default'>"+'Item Name'+"</td>";
        html+="<td class='tb-heading ui-state-default'>"+'Weightage'+"</td>";
        html+="</tr></table>";
        return html; 
}

//Add New Row


function addToRow(Weightage,ItemName,ItemNamenum){
    var html="<tr class='trObj'>";
    html+="<td>"+counts+"</td>";
    html+="<td>"+ItemName+"</td>";
    html+="<td>"+Weightage+"</td>";
    html+="</tr>";
    counts++;
    return html;
}

In my example, serial number is managed according to the actions taken on each row using css. I used a form inside each row, and when new row created then the form will get reset.

_x000D_
_x000D_
/*auto increment/decrement the sr.no.*/_x000D_
body {_x000D_
    counter-reset: section;_x000D_
}_x000D_
_x000D_
i.srno {_x000D_
    counter-reset: subsection;_x000D_
}_x000D_
_x000D_
i.srno:before {_x000D_
    counter-increment: section;_x000D_
    content: counter(section);_x000D_
}_x000D_
/****/
_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>_x000D_
<script type='text/javascript'>_x000D_
    $(document).ready(function () {_x000D_
        $('#POITable').on('change', 'select.search_type', function (e) {_x000D_
            var selectedval = $(this).val();_x000D_
            $(this).closest('td').next().html(selectedval);_x000D_
        });_x000D_
    });_x000D_
</script>_x000D_
<table id="POITable" border="1">_x000D_
    <tr>_x000D_
        <th>Sl No</th>_x000D_
        <th>Name</th>_x000D_
        <th>Your Name</th>_x000D_
        <th>Number</th>_x000D_
        <th>Input</th>_x000D_
        <th>Chars</th>_x000D_
        <th>Action</th>_x000D_
    </tr>_x000D_
    <tr>_x000D_
        <td><i class="srno"></i></td>_x000D_
        <td>_x000D_
            <select class="search_type" name="select_one">_x000D_
                <option value="">Select</option>_x000D_
                <option value="abc">abc</option>_x000D_
                <option value="def">def</option>_x000D_
                <option value="xyz">xyz</option>_x000D_
            </select>_x000D_
        </td>_x000D_
        <td></td>_x000D_
        <td>_x000D_
            <select name="select_two" >_x000D_
                <option value="">Select</option>_x000D_
                <option value="123">123</option>_x000D_
                <option value="456">456</option>_x000D_
                <option value="789">789</option>_x000D_
            </select>_x000D_
        </td>_x000D_
_x000D_
        <td><input type="text" size="8"/></td>_x000D_
        <td>_x000D_
            <select name="search_three[]" >_x000D_
                <option value="">Select</option>_x000D_
                <option value="one">1</option>_x000D_
                <option value="two">2</option>_x000D_
                <option value="three">3</option>_x000D_
            </select>_x000D_
        </td>_x000D_
        <td><button type="button" onclick="deleteRow(this)">-</button><button type="button" onclick="insRow()">+</button></td>_x000D_
    </tr>_x000D_
</table>_x000D_
_x000D_
<script type='text/javascript'>_x000D_
    function deleteRow(row)_x000D_
    {_x000D_
        var i = row.parentNode.parentNode.rowIndex;_x000D_
        document.getElementById('POITable').deleteRow(i);_x000D_
    }_x000D_
    function insRow()_x000D_
    {_x000D_
        var x = document.getElementById('POITable');_x000D_
        var new_row = x.rows[1].cloneNode(true);_x000D_
        var len = x.rows.length;_x000D_
        //new_row.cells[0].innerHTML = len; //auto increment the srno_x000D_
        var inp1 = new_row.cells[1].getElementsByTagName('select')[0];_x000D_
        inp1.id += len;_x000D_
        inp1.value = '';_x000D_
        new_row.cells[2].innerHTML = '';_x000D_
        new_row.cells[4].getElementsByTagName('input')[0].value = "";_x000D_
        x.appendChild(new_row);_x000D_
    }_x000D_
</script>
_x000D_
_x000D_
_x000D_

Hope this helps.