Mike
Mike

Reputation: 344

Nested Jquery each on 2D array incorrectly repeats table cells

I have a nested $.each over a 2-d array to generate a table that I can't figure out. It repeats the table cells for some reason. I've simplified it down as much as possible and still get the error.

HTML:

<table id="mytable" class="table table-bordered table-striped"></table>

javascript:

var header_array = ["one", "two", "three", "four", "five"];

$("#mytable").append("<thead><tr></tr></thead>");
$.each(header_array, function(index, value) {
    $("#mytable thead tr").append("<th>" + value + "</th>")
});

var data_array = [  ["one", "two", "three", "four", "five"],
                    ["one", "two", "three", "four", "five"],
                    ["one", "two", "three", "four", "five"]
                 ];

$("#mytable").append("<tbody></tbody>");            
$.each( data_array, function( index1, value1 ) {
    $("#mytable tbody").append("<tr></tr>");
    $.each( value1, function( index2, value2 ) {
        $("#mytable tbody tr").append("<td>"+ value2 + "</td>")
    });
});

For some reason the last part:

 $.each( value1, function( index2, value2 ) {
        $("#mytable tbody tr").append("<td>"+ value2 + "</td>")
    });

appends all of data_array in the first iteration, then 2/3 sub-arrays in data_array, then one sub-array of data_array, not just value1. Does anyone know why?

Thanks

http://jsfiddle.net/flyhunter/t63kxyfg/

Upvotes: 0

Views: 83

Answers (1)

Aaron
Aaron

Reputation: 228

Here's your original code:

$("#mytable").append("<tbody></tbody>");            
$.each( data_array, function( index1, value1 ) {
    $("#mytabletbody").append("<tr></tr>");
    $.each( value1, function( index2, value2 ) {
        $("#mytabletbody tr").append("<td>"+ value2 + "</td>")
    });
});

The first line of this snippet adds a new tbody to the end of the interior of the #mytable element. Next, you're looping through the rows of the 2D array (which is good). For each row, you're adding a new tr to the #mytabletbody element in the DOM. This is a problem, because nothing in your code indicates that there is actually an element in the DOM with id "mytabletbody". You could change this to be "#mytable > tbody" instead, which would find the #mytable element and search its direct children for all tbodys. However, you would still have a problem, because your next line of code loops through each element in the current row of the table. For each element in the row, it is executing the following line:

$("#mytabletbody tr").append("<td>"+ value2 + "</td>")

Now, the problem with this is that $("#mytabletbody tr") is finding all trs inside of #mytabletbody, which would select not only the current tr, but also any trs that have already been made. I would advise changing the code to work like this:

// Create variables that we will use to store JQuery objects
var $tbody, $tr, $td;

// Make a new <tbody>
$tbody = $("<tbody></tbody>"); 

// Loop through rows of array       
$.each( data_array, function( index1, value1 ) {
    // Make a new <tr>
    $tr = $("<tr></tr>");

    // Loop through elements of current row
    $.each( value1, function( index2, value2 ) {
        // Make a new <td> and set contents
        $td = $("<td></td>").html(value2);

        // Append current <td> to current <tr>
        $tr.append($td);
    });

    // Append current <tr> to <tbody>
    $tbody.append($tr);
});

// Append <tbody> to <table>
$("#mytable").append($tbody);

Here, we are creating and populating DOM elements before they are attached to the DOM. That way, we only have to do a single re-render of the DOM, when we finally attach the pre-created and pre-populated $tbody to #mytable.

Upvotes: 1

Related Questions