CallumVass
CallumVass

Reputation: 11448

Angular: Display 2D Array in table format

I have an array of data (lanes) which itself contains an array (timePeriods):

lanes: [{
 lane: 'Lane 1',
    timePeriods: [{
        start: '08:00',
        end: '08:15',
        trays: Math.floor(Math.random() * 6) + 1
    }, {
        start: '08:15',
        end: '08:30',
        trays: Math.floor(Math.random() * 6) + 1
    }, {
        start: '08:30',
        end: '08:45',
        trays: Math.floor(Math.random() * 6) + 1
    }, {
        start: '08:45',
        end: '09:00',
        trays: Math.floor(Math.random() * 6) + 1
    }]
 },
 ...
 ]

What I would like to do is display it in tabular format like so, but I'm not sure how to get the columns and rows lined up correctly? Would I need nested tables perhaps?

enter image description here

I've created a jsfiddle but just outputting static numbers for the trays, rather then the actual value of trays as I'm not sure how: http://jsfiddle.net/boe5u2sj/

Upvotes: 1

Views: 2555

Answers (2)

vernonner3voltazim
vernonner3voltazim

Reputation: 786

A single table should suffice, but the code could be rather messy/tedious. It could be a lot simpler if the data you put into that array was generated in some sort of loop, because you could use that same loop to put the data into the table. The HTML needs something like this:

<table id="tbl"></table>

Your JavaScript needs to access the table:

var tabl, rows=[], data=[];  //extra variables used farther down
tabl=document.getElementById("tbl");

Your loop that fills your array needs to create table-row and table-data elements, and fill them in semi-simultaneously with filling the array (assumes index-variables "i" and "j" here):

rows[i]=document.createElement("tr"); //table-row element
tabl.appendChild(rows[i]);
data[j]=document.createElement("td"); //table-data element
data[j].innerHTML="&nbsp;";  //top-left corner of table, blank/space, when i=0 and j=0
rows[i].appendChild(data[j]);

You would increment "j" and modify the innerHTML data for each data item you need in the first table row, fetching the data from your array (or applying it to the innerHTML at about the same time you put the data into the array, if the array is generated in a loop). For the second row, when i=1, you want the first data item's (j=0) innerHTML to be a time pulled from the array, a hyphen, and another time pulled from the array. The second data item's innerHTML would be one of your "trays" numbers. And so on. Just remember to use appendChild to append each row to the "tabl", and use appendChild to append data items to the current row. (Ummm...I might have that backward; you might have to fill in the row before appending it to the table, to ensure all the appendings actually become part of the table.) In the end, so long as there are the same number of data items per row, everything should be reasonably well aligned when the browser displays just-the-one constructed table on the web page. (If needed, you can specify "style" information prior to appending a data-element to a row-element.)

If you don't use loops, then the entire HTML table needs to be constructed, assigning each table-data element a unique "id". Your JavaScript then has to do getElementById() for every single one of those table-data elements, and assign the appropriate innerHTML value to it. Messy and tedious!

Upvotes: 0

bmleite
bmleite

Reputation: 26870

You can do it with a single <table>, just re-arrange the data before displaying it.

Since you are going to iterate over each row, it will be easier if you arranje the data like this (for example):

{
  "08:00-08:15": {
    "Lane 1": {
      "trays": 1
    },
    "Lane 2": {
      "trays": 6
    }
  },
  "08:15-08:30": {
    "Lane 1": {
      "trays": 4
    },
    "Lane 2": {
      "trays": 5
    }
  },
  ...

It order to do that, use something like this:

vm.rep = {};
_.forEach(vm.report.lanes, function(lane) {
    _.forEach(lane.timePeriods, function(timePeriod) {
        var time = timePeriod.start + "-" + timePeriod.end;
        if (vm.rep[time] == null) {
            vm.rep[time] = {};
        }
        vm.rep[time][lane.lane] = { trays: timePeriod.trays };
    });
});

And then, on the HTML:

<table class="table">
  <thead>
     <tr>
         <th><!-- time periods --></th>
         <th ng-repeat="lane in vm.lanes">{{lane}}</th>
      </tr>
  </thead>
  <tbody>
    <tr ng-repeat="(time, lanes) in vm.rep">
        <td>{{time}}</td>
        <td ng-repeat="(key, lane) in lanes">{{lane.trays}}</td>
    </tr>
  </tbody>
</table>

jsFiddle

Upvotes: 4

Related Questions