Creating a Comparison Table from a JQuery JSON Array

jquery

#1

Hi,

I have a JQuery Code with a JSON array and a radio-button selection. It’s currently giving me separate tables for each selected input. But the keys (row heading) are the same, I actually require each selection to appear to the right of the previous selection in a single table. Basically I need to build a simple comparison table to compare each option across parameters.

Once again, many thanks again for any help you can give me in this regard as I’ve been struggling long with this code.

    <!DOCTYPE html>
    <html>
        <head>
            <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
        </head>
     <style>
         .opt{
             margin: 10px;
             padding: 10px;
             background: #eee;
             border: 1px solid #222;
         }
         .select{
             font-family: Sans-serif;
             font-size : 10px;
             font-size: #222;
             font-style: italic;    
             }
     </style>   
    <body>
    Options:
    <input type="checkbox" name="Station" value="Opt1" class="select">Option1
    <input type="checkbox" name="Station" value="Opt2" class="select">Option2
    <input type="checkbox" name="Station" value="Opt3" class="select">Option3
    <input id="btnSubmit" type="submit" value="submit" />
    <br /><br />
    <div id="divResult"></div>
    </body> 

    <script>
        jQuery(document).ready(function( $ ){
            var StatJSON = {
            "Opt1":  {
                "Name": "Mat",
                "Parameter1": "65",
                "Parameter2": "30"
            },
            "Opt2": {
                "Name": "Mik",
                "Parameter1": "62",
                "Parameter2": "40"
            },
            "Opt3": {
                "Name": "Mir",
                "Parameter1": "65",
                "Parameter2": "90"
            }
        };

        $('#btnSubmit').click(function(){ 
        var resultString = '';
        $('input[type="checkbox"]:checked').each(function() {
        var this_input = $(this);
        if (this_input.is(':checked')){
        resultString += PrintHtml(StatJSON[$(this).val()]);
        }
        });
        $('#divResult').html(resultString);
        });
    });

    function PrintHtml(obj){
        var html='<div class="opt">';
        if (obj){
            $.each(obj, function(k,v){
                html += '<div>'+k+' : '+v+'</div>'; 
            });
        }
        html += '</div>';
        return html;
    }
    </script>
    </html>

#2

You’re passing a bunch of HTML to your PrintHtml function. That’s not good. Pass the data that that function needs and let it work out how to display it.

Probably best to use a table then, as this is tabular data.

If you don’t mind using ES6, this is how I’d do it:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Tablez</title>
    <style>#result { margin-top: 15px; }</style>
  </head>
  <body>
    Options:
    <input type="checkbox" name="Station" value="Opt1" class="select">Option1
    <input type="checkbox" name="Station" value="Opt2" class="select">Option2
    <input type="checkbox" name="Station" value="Opt3" class="select">Option3
    <input id="btnSubmit" type="submit" value="submit" />

    <div id="result"></div>

    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
    <script>
      var StatJSON = {
        "Opt1":  {
          "Name": "Mat",
          "Parameter1": "65",
          "Parameter2": "30"
        },
        "Opt2": {
          "Name": "Mik",
          "Parameter1": "62",
          "Parameter2": "40"
        },
        "Opt3": {
          "Name": "Mir",
          "Parameter1": "65",
          "Parameter2": "90"
        }
      };

      function buildTable(opts){
        return `
          <table>
            <thead>
              <tr>
                <th>Name</th>
                <th>Parameter1</th>
                <th>Parameter2</th>
              </tr>
            </thead>
            ${opts.map(opt => `
              <tr>
                <td>${opt.Name}</td>
                <td>${opt.Parameter1}</td>
                <td>${opt.Parameter2}</td>
              </tr>
            `).join('')}
          </table>
        `;
      }

      $('#btnSubmit').click(function(){
        const opts = $('input:checked')
          .map((i, input) => StatJSON[input.value])
          .get();
        $('#result').html(buildTable(opts));
      });
    </script>
  </body>
</html>

As the table header is hard coded, this wouldn’t be ideal for a lot of options, but it wouldn’t be difficult to make this dynamic, too.

HTH


#3

Hi @James_Hibbard. Thanks!! This is what I wanted and this code is much simpler & functional than what I had. :slight_smile: But is it possible to switch the column headings to row headings?! I tried swapping the <tr> and <td> but that didn’t work. :confused: I was trying to build a comparison table where columns appear beside each other as we select the options like the table below.

Compare%20options


#4

Sure, that’s possible. You could do it like this:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Tablez</title>
    <style>#result { margin-top: 15px; }</style>
  </head>
  <body>
    Options:
    <input type="checkbox" name="Station" value="Opt1" class="select">Option1
    <input type="checkbox" name="Station" value="Opt2" class="select">Option2
    <input type="checkbox" name="Station" value="Opt3" class="select">Option3
    <input id="btnSubmit" type="submit" value="submit" />

    <div id="result"></div>

    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
    <script>
      var StatJSON = {
        "Opt1":  {
          "Name": "Mat",
          "Parameter1": "65",
          "Parameter2": "30"
        },
        "Opt2": {
          "Name": "Mik",
          "Parameter1": "62",
          "Parameter2": "40"
        },
        "Opt3": {
          "Name": "Mir",
          "Parameter1": "65",
          "Parameter2": "90"
        }
      };

      function buildTable(opts){
        const keys = Object.keys(opts[0])
        const headers = ['', 'Name', 'Parameter 1', 'Parameter 2'];
        const rows = keys.map(key => opts.map(opt => opt[key]));

        return `
          <table>
            ${headers.map((header, i) =>  `
              <tr>
                <th>${header}</th>
                ${rows[i].map((row, j) => `<td>${rows[i][j]}</td>`).join('')}
              </tr>
            `).join('')}
          </table>
        `;
      }

      $('#btnSubmit').click(function(){
        const opts = $('input:checked')
          .map((i, input) => $.extend({Nr: input.value}, StatJSON[input.value]))
          .get();
        $('#result').html(buildTable(opts));
      });
    </script>
  </body>
</html>

Hooowever, although this works, the code is pretty awful to read and when you revisit it at a later date, you’ll think “WTF was going on here??”. This is largely due to the fact that you want to display the table headers on the left and what should be the table rows, vertically as opposed to horizontally.

So if I was you, I’d start looking for a way to make this a bit easier to understand. Maybe look into using a template engine, or reconsider the data structure you are using.