Display Array Data in an a Tabular Format

By Rob Gravelle

Display Array Data in an a Tabular Format

Most languages provide plenty of array utility functions from slicing(), merging, flattening(), filtering() and mapping(), but one thing that you typically have to do yourself is transform arrays to display them in a tabular format. Why would you want to do this? Presenting information in a table is a great way to separate categories, sort elements, as well as maximize screen real estate. I recently arranged an array of objects into a 4 x 3 table of checkboxes in order to avoid having a list of up to 15 items, which would necessitate a lot of scrolling on the user's part. In today's article, I'll show you how to dynamically transform the contents of a one-dimension array into an HTML table on both the server and client, using PHP and JavaScript respectively.

The Array Structure

For the purposes of today's examples, the display function expects an array of objects where each has two properties: a slug (unique key) and name (label):

  • Element 1: {slug: 'menu_allergen_milk', name: 'Milk'}
  • Element 2: {slug: 'menu_allergen_peanut', name: 'Peanuts'}
  • Element 3: {slug: 'menu_allergen_sulphites', name: 'Sulphur dioxide'}
  • Element 4: {slug: 'menu_allergen_celery', name: 'Celery'}
  • Element 5: {slug: 'menu_allergen_seafood', name: 'Seafood'}
  • Element 6: {slug: 'menu_allergen_mustard', name: 'Mustard'}
  • etc...

Producing an HTML Table using PHP

Whatever language you employ to implement the functionality, the idea is always the same:

  1. Print out the start of the table, up to, but not including the first <TR> row tag.
  2. Iterate over each array element.
    For each element:
    1. If it's the first cell, print the <TR> row tag.
    2. Print the table cell and element contents.
    3. If we've printed the number of columns that we want, print the closing <TR> row tag and reset the cell counter.
  3. Print out the end of the table.

Here is the above operation in PHP code:

//for displaying columns of checkboxes
function transform_allergens_array_to_table($column_count) {
  $cell_index = 1;
  $html .= '<table name="tblMenuAllergens" width="" cellpadding="1"><thead></thead><tbody>';
  for ($i=0; $i < $menu_tags_len; $i++ ) {
    if ($cell_index == 1) { $html .= '<tr>'; }
    $id    = $menu_tags[$i]['slug'];
    $name  = $menu_tags[$i]['name'];
 
    $html .= '<td width="110"><input type="checkbox" name="menu[' . $type . '][]" value="' . $id . '" id="' . $id . '" ';
    if (array_search($id, $saved_menu_tags) !== false) { $html .=  'checked="checked"'; }
    $html .= '><label for="' . $id . '">' . $name . '</label></td>' . "\n";
    if ( ++$cell_index > $column_count ) { //close the row
      $html .= '</tr>' . "\n";
      $cell_index = 1;
    }
  }
  $html .= '</tbody></table>' . "\n";
       
  return $html;
}

Here is an example of the HTML markup produced:

<table name="tblMenuAllergens" width="" cellpadding="1">
  <tbody>
    <tr>
      <td width="140">
        <input type="checkbox" name="menu[breakfasts][]"
        value="menu_allergen_gluten" id=
        "menu_allergen_gluten"><label for=
        "menu_allergen_gluten">Gluten</label>
      </td>
      <td width="140">
        <input type="checkbox" name="menu[breakfasts][]"
        value="menu_allergen_milk" id=
        "menu_allergen_milk" checked="checked"><label for=
        "menu_allergen_milk">Milk/lactose</label>
      </td>
      <td width="140">
        <input type="checkbox" name="menu[breakfasts][]"
        value="menu_allergen_eggs" id=
        "menu_allergen_eggs"><label for=
        "menu_allergen_eggs">Eggs</label>
      </td>
      <td width="140">
        <input type="checkbox" name="menu[breakfasts][]"
        value="menu_allergen_fish" id=
        "menu_allergen_fish"><label for=
        "menu_allergen_fish">Fish</label>
      </td>
    </tr>
    <tr>
      <td width="140">
        <input type="checkbox" name="menu[breakfasts][]"
        value="menu_allergen_peanut" id=
        "menu_allergen_peanut" checked="checked"><label for=
        "menu_allergen_peanut">Peanuts</label>
      </td>
      <td width="140">
        <input type="checkbox" name="menu[breakfasts][]"
        value="menu_allergen_nut" id=
        "menu_allergen_nut" checked="checked"><label for=
        "menu_allergen_nut">Nuts</label>
      </td>
      <td width="140">
        <input type="checkbox" name="menu[breakfasts][]"
        value="menu_allergen_soya_beans" id=
        "menu_allergen_soya_beans"><label for=
        "menu_allergen_soya_beans">Soyabeans</label>
      </td>
      <td width="140">
        <input type="checkbox" name="menu[breakfasts][]"
        value="menu_allergen_celery" id=
        "menu_allergen_celery"><label for=
        "menu_allergen_celery">Celery/celeriac</label>
      </td>
    </tr>
    <tr>
      <td width="140">
        <input type="checkbox" name="menu[breakfasts][]"
        value="menu_allergen_mustard" id=
        "menu_allergen_mustard"><label for=
        "menu_allergen_mustard">Mustard</label>
      </td>
      <td width="140">
        <input type="checkbox" name="menu[breakfasts][]"
        value="menu_allergen_sesame" id=
        "menu_allergen_sesame"><label for=
        "menu_allergen_sesame">Sesame seeds</label>
      </td>
      <td width="140">
        <input type="checkbox" name="menu[breakfasts][]"
        value="menu_allergen_lupin_flour" id=
        "menu_allergen_lupin_flour"><label for=
        "menu_allergen_lupin_flour">Lupin</label>
      </td>
      <td width="140">
        <input type="checkbox" name="menu[breakfasts][]"
        value="menu_allergen_crustacean" id=
        "menu_allergen_crustacean"><label for=
        "menu_allergen_crustacean">Crustaceans</label>
      </td>
    </tr>
    <tr>
      <td width="140">
        <input type="checkbox" name="menu[breakfasts][]"
        value="menu_allergen_molluscs" id=
        "menu_allergen_molluscs"><label for=
        "menu_allergen_molluscs">Molluscs</label>
      </td>
      <td width="140">
        <input type="checkbox" name="menu[breakfasts][]"
        value="menu_allergen_sulphites" id=
        "menu_allergen_sulphites"><label for=
        "menu_allergen_sulphites">Sulphur dioxide</label>
      </td>
    </tr>
  </tbody>
</table>

And here's what the generated table looks like:

One More Time in JavaScript

Accomplishing the same thing in JavaScript requires surprisingly few syntax changes. In the following client-side code, the selected allergens are displayed within a table in a read-only format - i.e., without the checkboxes. Another change is that empty cells are added to complete the last row if necessary. It just looks better with borders.

I prefer to place the script at the bottom of the page and invoke printArrayInTabularFormat() as an inline function. You can even pass arguments to it by including them in the closing parentheses!

var $menu_tags = [
  {slug: 'menu_allergen_milk',    name: 'Milk'},
  {slug: 'menu_allergen_peanut',    name: 'Peanuts'},
  {slug: 'menu_allergen_sulphites', name: 'Sulphur dioxide'},
  {slug: 'menu_allergen_celery',    name: 'Celery'},
  {slug: 'menu_allergen_seafood',   name: 'Seafood'},
  {slug: 'menu_allergen_mustard',   name: 'Mustard'}
]; 
var MENU_TAGS_COLUMN_COUNT = 4;

(function printArrayInTabularFormat(menuTags, colCount) {
    var html = '<table name="tblMenuAllergens" cellpadding="1" border="1"><thead></thead><tbody>' + "\n";

    var cellIndex=1;
    for (var $i=0; $i<menuTags.length; $i++) {
      if (cellIndex == 1) {
        html += '<tr>';
      }
      var $id    = menuTags[$i]['slug'];
      var $name  = menuTags[$i]['name'];
      html += '<td width="120">' + $name + '</td>' + "\n";
      if (++cellIndex > colCount) { //close the row
        html += '</tr>';
        cellIndex = 1;
      }
    }
    //finish empty cells
    var remainingCellsCount = menuTags.length % colCount;
    if (remainingCellsCount) {
      for (var $i=0; $i<remainingCellsCount; $i++) {
        html += '<td width="120"> </td>' + "\n";
      }
      html += '</tr>';
    }
    html += '</tbody></table>' + "\n";
    html += '</td></tr></tbody></table>' + "\n";
   
    document.getElementById('allergensTable').innerHTML = html;
})($menu_tags, MENU_TAGS_COLUMN_COUNT);

Here is the generated code this time:

<table name="tblMenuAllergens" cellpadding="1" border="1">
  <tbody>
    <tr>
      <td width="120">
        Milk
      </td>
      <td width="120">
        Peanuts
      </td>
      <td width="120">
        Sulphur dioxide
      </td>
      <td width="120">
        Celery
      </td>
    </tr>
    <tr>
      <td width="120">
        Seafood
      </td>
      <td width="120">
        Mustard
      </td>
      <td width="120">
         &nbsp;
      </td>
      <td width="120">
         &nbsp;
      </td>
    </tr>
  </tbody>
</table>

...which looks like this in the browser:

Milk Peanuts Sulphur dioxide Celery
Seafood Mustard    

Conclusion

For best results I would remove all of the table, row, and cell attributes and move them to a CSS file. That would help make the function as generic as possible.



Rob Gravelle

Rob Gravelle resides in Ottawa, Canada, and is the founder of GravelleWebDesign.com. Rob has built systems for Intelligence-related organizations such as Canada Border Services, CSIS as well as for numerous commercial businesses.

In his spare time, Rob has become an accomplished guitar player, and has released several CDs. His band, Ivory Knight, was rated as one Canada's top hard rock and metal groups by Brave Words magazine (issue #92) and reached the #1 spot in the National Heavy Metal charts on Reverb Nation.



Make a Comment

Loading Comments...

  • Web Development Newsletter Signup

    Invalid email
    You have successfuly registered to our newsletter.
  •  
  •  
  •  
Thanks for your registration, follow us on our social networks to keep up-to-date