0

I've search through the similar questions but none answered my problem. (all those problems seemed related to typos)

I'm just making this for fun. I'm creating a table using jquery based on json data. Problem is, the appended table rows don't inherit any of the CSS rules. I feel like I've read about the cause for this before, specifically to tables, but the info eludes me.

HTML:

            <table width="100%" class="" id="mytable">
                <thead>
                </thead>
                <tbody>
                <tr><td>f</td><td></td><td></td><td></td></tr>
                <tr><td>b</td><td></td><td></td><td></td></tr>
                <tr><td>a</td><td></td><td></td><td></td></tr>
                </tbody>
            </table>

CSS:

    tr:nth-child(even){background:blue}
    tr:nth-child(odd){background:green}

JS:

        // Build some test data
        var data = [];
        var cols = ['Col-A','Col-B','Col-C','Col-D'];
        for (i=0;i<10;i++){
            data.push(['A_'+i,'B_'+i,'C_'+i,'D_'+i]);
        }
        // data that would be sent to 
        var json = JSON.stringify({columns:cols, data:data});


        // build the table
        $('#mytable').tables(json);


    });


    // the magic function
    jQuery.fn.tables = function(json) {
        var obj = JSON.parse(json);
        var head = this.find('thead');
        var bod  = this.find('tbody');

        // Build columns
        head.append('<tr>');
        for (i=0;i<obj.columns.length;i++){
            head.append('<th>'+obj.columns[i]+'</th>');

        }
        head.append('</tr>');

        // Add row data
        for (i=0;i<obj.data.length;i++){
            bod.append('<tr>');
            for(j=0;j<obj.data[i].length;j++){
                bod.append('<td>'+obj.data[i][j]+'</td>');
            }
            bod.append('</tr>');    
        }

        return this;
    }
Phaelax z
  • 1,814
  • 1
  • 7
  • 19

2 Answers2

2

With this code you don't append one full row at a time, but only fragments. What you'll expect to be rendered?

head.append('<tr>');
...
head.append('</tr>');

For this to work, your magic function should be something like this:

    // the magic function
    jQuery.fn.tables = function(json) {
        var obj = JSON.parse(json);
        var head = this.find('thead');
        var bod  = this.find('tbody');



        // Build columns
        var row = '<tr>';
        for (i=0;i<obj.columns.length;i++){
            row += '<th>'+obj.columns[i]+'</th>';
        }
        row += '</tr>';

        head.append(row); // append the full row

        // Add row data
        row = '';
        for (i=0;i<obj.data.length;i++){
            row += '<tr>';
            for(j=0;j<obj.data[i].length;j++){
                row += '<td>'+obj.data[i][j]+'</td>';
            }
            row += '</tr>';
        }

        bod.append(row); // append the full row

        return this;
    }

Function which appends one full row at a time.

Razvan Theodor
  • 183
  • 1
  • 9
  • Gotcha. But I don't understand why it has to be a full row at a time. It's the same data in the end being added so wouldn't it see the full rows then? – Phaelax z Nov 21 '19 at 20:50
  • I don't know precisely why. I think if you open an html tag, you should also close it to be a full element appended. – Razvan Theodor Nov 21 '19 at 21:14
0

@Razvan hit the nail on the head, but I think there is a much more idiomatic way of doing this. After all, we are using jQuery, so we might as well be efficient.

jQuery.fn.tables = function(json) {
  var obj = JSON.parse(json);
  var head = this.find('thead');
  var bod  = this.find('tbody');
  
  // Build columns
  head.append($('<tr>').append(obj.columns.map(e => $('<th>').text(e))));

  // Add row data
  obj.data.forEach(r => bod.append($('<tr>').append(r.map(e => $('<td>').text(e)))));

  return this;
}
    
// Build some test data
var data = [];
var cols = ['Col-A','Col-B','Col-C','Col-D'];
for (i=0;i<10;i++){
    data.push(['A_'+i,'B_'+i,'C_'+i,'D_'+i]);
}
// data that would be sent to 
var json = JSON.stringify({columns:cols, data:data});


// build the table
$('#mytable').tables(json);
tr:nth-child(even){background:blue}
tr:nth-child(odd){background:green}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table width="100%" class="" id="mytable">
    <thead>
    </thead>
    <tbody>
    <tr><td>f</td><td></td><td></td><td></td></tr>
    <tr><td>b</td><td></td><td></td><td></td></tr>
    <tr><td>a</td><td></td><td></td><td></td></tr>
    </tbody>
</table>

Basically, I use a couple chained-together arrow functions along with .forEach and .map to append the <td> and <th> elements to the respective rows and append the rows to the table in a single statement.

StardustGogeta
  • 3,331
  • 2
  • 18
  • 32
  • 1
    Of course @PhaelaxZ's function can be reduced or simplified. I've been focused however on a simple answer which clarifies the problem. – Razvan Theodor Nov 21 '19 at 20:58
  • 1
    @RazvanTheodor That makes sense, and I upvoted your answer. I just thought that this would be worth mentioning just in case the OP didn't know the simpler way of doing it. – StardustGogeta Nov 21 '19 at 21:06
  • Add table row in jQuery https://stackoverflow.com/questions/171027/add-table-row-in-jquery – Razvan Theodor Nov 21 '19 at 21:10