Community Documentation

theme_table

5 theme.inc theme_table($header, $rows, $attributes = array(), $caption = NULL)
6 theme.inc theme_table($header, $rows, $attributes = array(), $caption = NULL)
7 theme.inc theme_table($variables)
8 theme.inc theme_table($variables)

Returns HTML for a table.

Parameters

$variables: An associative array containing:

  • header: An array containing the table headers. Each element of the array can be either a localized string or an associative array with the following keys:

    • "data": The localized title of the table column.
    • "field": The database field represented in the table column (required if user is to be able to sort on this column).
    • "sort": A default sort order for this column ("asc" or "desc").
    • Any HTML attributes, such as "colspan", to apply to the column header cell.
  • rows: An array of table rows. Every row is an array of cells, or an associative array with the following keys:

    • "data": an array of cells
    • Any HTML attributes, such as "class", to apply to the table row.
    • "no_striping": a boolean indicating that the row should receive no 'even / odd' styling. Defaults to FALSE.

    Each cell can be either a string or an associative array with the following keys:

    • "data": The string to display in the table cell.
    • "header": Indicates this cell is a header.
    • Any HTML attributes, such as "colspan", to apply to the table cell.

    Here's an example for $rows:

<?php
    $rows = array(
      // Simple row
      array(
        'Cell 1', 'Cell 2', 'Cell 3'
      ),
      // Row with attributes on the row and some of its cells.
      array(
        'data' => array('Cell 1', array('data' => 'Cell 2', 'colspan' => 2)), 'class' => array('funky')
      )
    );
    ?>
  • attributes: An array of HTML attributes to apply to the table tag.
  • caption: A localized string to use for the <caption> tag.
  • colgroups: An array of column groups. Each element of the array can be either:

    • An array of columns, each of which is an associative array of HTML attributes applied to the COL element.
    • An array of attributes applied to the COLGROUP element, which must include a "data" attribute. To add attributes to COL elements, set the "data" attribute with an array of columns, each of which is an associative array of HTML attributes.

    Here's an example for $colgroup:

<?php
    $colgroup = array(
      // COLGROUP with one COL element.
      array(
        array(
          'class' => array('funky'), // Attribute for the COL element.
        ),
      ),
      // Colgroup with attributes and inner COL elements.
      array(
        'data' => array(
          array(
            'class' => array('funky'), // Attribute for the COL element.
          ),
        ),
        'class' => array('jazzy'), // Attribute for the COLGROUP element.
      ),
    );
    ?>

These optional tags are used to group and set properties on columns within a table. For example, one may easily group three columns and apply same background style to all.

  • sticky: Use a "sticky" table header.
  • empty: The message to display in an extra row if table does not have any rows.

Related topics

File

includes/theme.inc, line 1770
The theme system, which controls the output of Drupal.

Code

<?php
function theme_table($variables) {
  $header = $variables['header'];
  $rows = $variables['rows'];
  $attributes = $variables['attributes'];
  $caption = $variables['caption'];
  $colgroups = $variables['colgroups'];
  $sticky = $variables['sticky'];
  $empty = $variables['empty'];

  // Add sticky headers, if applicable.
  if (count($header) && $sticky) {
    drupal_add_js('misc/tableheader.js');
    // Add 'sticky-enabled' class to the table to identify it for JS.
    // This is needed to target tables constructed by this function.
    $attributes['class'][] = 'sticky-enabled';
  }

  $output = '<table' . drupal_attributes($attributes) . ">\n";

  if (isset($caption)) {
    $output .= '<caption>' . $caption . "</caption>\n";
  }

  // Format the table columns:
  if (count($colgroups)) {
    foreach ($colgroups as $number => $colgroup) {
      $attributes = array();

      // Check if we're dealing with a simple or complex column
      if (isset($colgroup['data'])) {
        foreach ($colgroup as $key => $value) {
          if ($key == 'data') {
            $cols = $value;
          }
          else {
            $attributes[$key] = $value;
          }
        }
      }
      else {
        $cols = $colgroup;
      }

      // Build colgroup
      if (is_array($cols) && count($cols)) {
        $output .= ' <colgroup' . drupal_attributes($attributes) . '>';
        $i = 0;
        foreach ($cols as $col) {
          $output .= ' <col' . drupal_attributes($col) . ' />';
        }
        $output .= " </colgroup>\n";
      }
      else {
        $output .= ' <colgroup' . drupal_attributes($attributes) . " />\n";
      }
    }
  }

  // Add the 'empty' row message if available.
  if (!count($rows) && $empty) {
    $header_count = 0;
    foreach ($header as $header_cell) {
      if (is_array($header_cell)) {
        $header_count += isset($header_cell['colspan']) ? $header_cell['colspan'] : 1;
      }
      else {
        $header_count++;
      }
    }
    $rows[] = array(array(
        'data' => $empty,
        'colspan' => $header_count,
        'class' => array('empty', 'message'),
      ));
  }

  // Format the table header:
  if (count($header)) {
    $ts = tablesort_init($header);
    // HTML requires that the thead tag has tr tags in it followed by tbody
    // tags. Using ternary operator to check and see if we have any rows.
    $output .= (count($rows) ? ' <thead><tr>' : ' <tr>');
    foreach ($header as $cell) {
      $cell = tablesort_header($cell, $header, $ts);
      $output .= _theme_table_cell($cell, TRUE);
    }
    // Using ternary operator to close the tags based on whether or not there are rows
    $output .= (count($rows) ? " </tr></thead>\n" : "</tr>\n");
  }
  else {
    $ts = array();
  }

  // Format the table rows:
  if (count($rows)) {
    $output .= "<tbody>\n";
    $flip = array(
      'even' => 'odd',
      'odd' => 'even',
    );
    $class = 'even';
    foreach ($rows as $number => $row) {
      $attributes = array();

      // Check if we're dealing with a simple or complex row
      if (isset($row['data'])) {
        foreach ($row as $key => $value) {
          if ($key == 'data') {
            $cells = $value;
          }
          else {
            $attributes[$key] = $value;
          }
        }
      }
      else {
        $cells = $row;
      }
      if (count($cells)) {
        // Add odd/even class
        if (empty($row['no_striping'])) {
          $class = $flip[$class];
          $attributes['class'][] = $class;
        }

        // Build row
        $output .= ' <tr' . drupal_attributes($attributes) . '>';
        $i = 0;
        foreach ($cells as $cell) {
          $cell = tablesort_cell($cell, $header, $ts, $i++);
          $output .= _theme_table_cell($cell);
        }
        $output .= " </tr>\n";
      }
    }
    $output .= "</tbody>\n";
  }

  $output .= "</table>\n";
  return $output;
}
?>

Comments

requires associative array in final theme call

The final call to the theme function needs to pass in an associative array as well which appears to have been changed for D7.

$output = theme('table', array('header' => $header, 'rows' => $rows));

Multi-row support for header

Please add support for multiple rows in the table header or document how to achieve this with the existing function.

Cells can also be render arrays.

This seems to be undocumented as of yet, but the internal api function _theme_table_cell has a special condition when the cell (each element in a row array) is defined using the 'data' variant. When using this definition, if you specify an array instead of a string, it will drupal_render the contents.

For instance :

<?php
foreach ($objects as $key => $object) {
   
// this is the well documented format
   
$options[$key]['title'] = filter_xss($object->title);

   
// this is the not well known format
   
$options[$key]['awesomeness'] =  array(
     
'data' => array(
       
'#type' => 'select',
       
'#options' => array(
         
'0' => t('boring'),
         
'1' => t('Awesome!'),
         
'11' => t('TURNED UP TO ELEVEN!!11!')
        ),
       
'#default_value' => $object->awesomeness,
     ));
}

$form['things'] = array(
   
'#type' => 'tableselect',
   
'#header' => array('title' => t('Title'), 'awesomeness' => t('AWESOMENESS')),
   
'#options' => $options,
   
'#empty' => t('No items available'),
  );
?>

This means you no longer have to have your own '#theme' function on the form to render the elements in the right cells.
This in turn means that you could end up deleting hundreds of lines of complex code that confuses themers and coders alike.

Yes, but not processed by FAPI

They can be renderable arrays but this way they are not processed by the FAPI because the form elements are in a property (starts with '#') and they are not children of the tableselect element (tableselect itself is not a container). (So AJAX won't work out of the box for example and they won't be in the values array for form submissions - only in input.)

Unable to add class to table attributes

This code does work. it gives a fetal error.

theme('table', array(
    'header' => $header,
    'rows' => $rows,
    'attributes' => array('class' => 'mytable')
));

Fatal error: [] operator not supported for strings in C:\wamp\www\damjd\includes\theme.inc on line 1633

But the code below works.

theme('table', array(
    'header' => $header,
    'rows' => $rows,
    'attributes' => array('width' => '100%')
));

You can use class attribute

You can use class attribute as an array:

<?php
theme
('table', array(
 
'header' => $header,
 
'rows' => $options,
 
'attributes' => array('class' => array('mytable'))
));
?>

and it's works fine.

Sticky headers & IE8

Sometimes sticky headers will crash IE8. I haven't been able to reproduce this, but just in case anyone else is trying to figure out IE8 crashes on validated HTML and using theme_table properly, it's probably sticky headers.

Try to sort id (for th) headers (for td)

I am trying to make Drupal assign column names as "id" to table headers and "headers" to table datas.
I want to add this option to templates.php
I think "theme_table" and "_theme_table_cell" functions" can do it, but I don't know how, and the second is not overridable.

I wrote this foreach loop

<?php
   
foreach($header as $headings){
    if (
is_array($headings)){
   
$headers=$headings['data'] . " ";
    echo
$headers;
        }
    else
    {
   
$headers=$headings . " ";
    echo
$headers;
        }
    };
?>

which shows all of the column titles
As I clear the cache a message alerts that "data" is an undefined index in overridden function "theme_table".

Further I don't know how to assign the results to single cells.

Wondering how to add ajax, FAPI style in table

So as you say, my form elements within a table cell don't have ajax attached to them. Could you point me in the right direction, where to start attaching it manually?

Thanks muchly

Putting a table in an render output array

Not finding anything on this, and thinking I'm missing a #type. How do I make this work:

$output['legend'] =  array(
            '#theme' => 'table',
            '#prefix' => '<div style="width: 250px"><h3>Legend</h3>',
            '#suffix' => '</div>',
            'content' => array('header' => array(), 'rows' => $legend)
          );

I get warnings/errors if I

I get warnings/errors if I don't specifically pass attributes, caption, colgroups, sticky, empty. This is very annoying.

Class should be set to an array of class names

One thing I'd like to note in regards to the class attribute and sticky...

If you are setting an attribute 'class', you must do it like this:

'attributes' => array('class' => array('table_dfs')),

...so 'class' is an array of class names (not a string).

I was not doing this, and when I set sticky => TRUE, my page was bombing out because it was trying to add another element to the class array which was a string.

Login or register to post comments