Same name and namespace in other branches
- 4.6.x includes/theme.inc \theme_table()
- 4.7.x includes/theme.inc \theme_table()
- 5.x includes/theme.inc \theme_table()
- 6.x includes/theme.inc \theme_table()
Returns HTML for a table.
Parameters
array $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"). Only one column should be given a default sort order because table sorting only applies to one column at a time.
- 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:
$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',
),
),
);- footer: An array of table rows which will be printed within a <tfoot> tag, in the same format as the rows element (see above). The structure is the same the one defined for the "rows" key except that the no_striping boolean has no effect, there is no rows striping for the table footer.
- 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:
$colgroup = array(
// COLGROUP with one COL element.
array(
array(
'class' => array(
'funky',
),
),
),
// Colgroup with attributes and inner COL elements.
array(
'data' => array(
array(
'class' => array(
'funky',
),
),
),
'class' => array(
'jazzy',
),
),
);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.
Return value
string The HTML output.
Related topics
68 theme calls to theme_table()
- aggregator_view in modules/
aggregator/ aggregator.admin.inc - Displays the aggregator administration page.
- book_admin_overview in modules/
book/ book.admin.inc - Returns an administrative overview of all books.
- contact_category_list in modules/
contact/ contact.admin.inc - Categories/list tab.
- dblog_event in modules/
dblog/ dblog.admin.inc - Page callback: Displays details about a specific database log message.
- dblog_overview in modules/
dblog/ dblog.admin.inc - Page callback: Displays a listing of database log messages.
File
- includes/
theme.inc, line 1996 - The theme system, which controls the output of Drupal.
Code
function theme_table(array $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 (!empty($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 (!empty($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 (empty($rows) && $empty) {
$header_count = 0;
if (!empty($header)) {
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 (!empty($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 .= !empty($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 .= !empty($rows) ? " </tr></thead>\n" : "</tr>\n";
}
else {
$ts = array();
}
// Format the table and footer rows.
$sections = array();
if (!empty($rows)) {
$sections['tbody'] = $rows;
}
if (!empty($variables['footer'])) {
$sections['tfoot'] = $variables['footer'];
}
// tbody and tfoot have the same structure and are built using the same
// procedure.
foreach ($sections as $tag => $content) {
$output .= "<" . $tag . ">\n";
$flip = array(
'even' => 'odd',
'odd' => 'even',
);
$class = 'even';
$default_no_striping = $tag === 'tfoot';
foreach ($content as $number => $row) {
// Check if we're dealing with a simple or complex row.
if (isset($row['data'])) {
$cells = $row['data'];
$no_striping = isset($row['no_striping']) ? $row['no_striping'] : $default_no_striping;
// Set the attributes array and exclude 'data' and 'no_striping'.
$attributes = $row;
unset($attributes['data']);
unset($attributes['no_striping']);
}
else {
$cells = $row;
$attributes = array();
$no_striping = $default_no_striping;
}
if (!empty($cells)) {
// Add odd/even class.
if (!$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 .= "</" . $tag . ">\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.
If anyone has any workaround
If anyone has any workaround for multiple rows in the table header, please do share. Thanks.
The workaraund I used was not
The workaraund I used was not to create a 'header' key but include the header in the 'rows' section.
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 :
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.)
so no system_settings_form() too
trying to do a settings table with theme_table and system_settings_form seems not to work for this very reason.
This may help you http:/
This may help you http://stackoverflow.com/questions/1981781/embedding-an-ahah-form-elemen...
Unable to add class to table attributes
This code does work. it gives a fetal error.
Fatal error: [] operator not supported for strings in C:\wamp\www\damjd\includes\theme.inc on line 1633
But the code below works.
You can use class attribute
You can use class attribute as an array:
and it's works fine.
There is an issue
... for fixing this in documentation: http://drupal.org/node/1135020 -- Need standard way to document the format of attributes in theme functions
width: auto
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.
I just ran into this myself
I just ran into this myself too. It's combination of having breadcrumb hidden and sticky headers enabled. I was able to get sticky headers working on IE8 after adding one element with class="element-invisible" to the place where breadcrumb normally was (theme based on bartik).
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
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
No even attaching it manually
No even attaching it manually wouldn't work! here is the solution http://stackoverflow.com/questions/1981781/embedding-an-ahah-form-elemen...
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:
Use this format
Use this format instead
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:
...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.
FYI, default sort order does
FYI, default sort order does not work in D7, and the header-related documentation on this page appears to be incorrect in any case.
re: default sort order, see this bug: http://drupal.org/node/109493
For sorting, the header items need these keys: data, type & specifier.
For an entity's native properties, that's where it ends. But for fields you've added to the entity, the specifier should be an array with 'field' and 'column' keys. Here is an example:
Note that the sort value has no effect because of the above-mentioned bug.
Then again, it may be that
Then again, it may be that these docs were written to encourage coding in a way that's consistent with how the sort feature will work when it's fixed?
Drupal 7 example
Posted by greggles on September 21, 2009 at 5:30pm
From berdir:
TableSort now works as an Extender, so you need to convert your query
to a dynamic db_select() query.
You then need to extend it with "->extend('TableSort')" and add the
table header by calling "->orderByHeader($header)".
Some Links:
An example from core: http://api.drupal.org/api/function/poll_votes/7
Extender doc page: http://drupal.org/node/508796
Individual TD Classes
The example above can be extended as:
Adding td classes with:
Structure Visualization of Nesting Scheme (tr, td, class)
This snippet helps to visualize the whole nesting scheme in a super simple manner. Additionally, it really works very fine in everyday life (hint: in a looping control structure you just have to substitute the first line with '
$arr_rows[] =' ).PHP
print_R output
For sticky
$output = theme('table', array(
'header' => $header,
'rows' => $rows,
'sticky' => TRUE, // or FALSE
)
);
Does not rendering in the Output(How do I do that?)
I have used exactly same code..
$output = theme('table', array(
'header' => $header,
'rows' => $row,
'attributes' => array('width' => '100%')
));
dpm($output);
}
drupal_render($output);
}
dpm($output) give me bunchof table tags(HTML), but I can not able to reder those elements in the page..what do i do to render the elements
I don't know what the rest of
I don't know what the rest of your code looks like, but try just doing:
return $output;no_striping
The no striping option has an issue and is being worked on here: http://drupal.org/node/935066
TableSort on Numbers Stored as String Values
If you want the user to be able to sort on a column that has numbers, but the field was created as a string (text), you can get proper numerical sorting by converting the value in the query using the SQL functions CAST() or CONVERT() in a query addExpression function as in:
SelectQuery + TableSort + theme_table + form_element
this is like the most common way for me to use theme_table, i though it might save somebody else's time
$headers = array(
'user' => array('data' => t('Username'), 'field' => 'u.name'),
'status' => array('data' => t('Status'), 'field' => 'u.status'),
'ops' => array('date' => t('Operations'))
);
$query = db_select('users', 'u')
->extend('TableSort');
$result = $query->fields('u', array('uid', 'name', 'status'))
->orderByHeader($headers)
->execute();
$rows = array();
foreach ($result as $invited_users) {
$rows[$invited_users->uid] = array(
'username' => l($invited_users->name, 'user/' . $invited_users->uid),
'status' => $invited_users->status,
'ops' => l('delete', 'delete')
);
}
$form['invited_users'] = array(
'#markup' => theme('table', array(
'header' => $headers,
'rows' => $rows,
'attributes' => array('class' => array('invited_users')),
'#empty' =>t('No invited users yet'),
))
);
Great Example
Thank you for posting this -- I intend to go through it so I understand how it's working. Looks like a very compact way to accomplish a lot. I've worked with Drupal for years but haven't used forms much, like the idea of giving the theme_table right to the form itself. There is always something new to learn here.
Export Table API data to csv
If you have setup your data and headers to work with Table api, such as below:
This snippet will let you then export it to csv. You'll need to put this in it's own function.
This didn't work for me. I
This didn't work for me. I needed to nest $rows in an extra array.
Not ok
Ok
Building rows doesn't account for colspan in the header
The loop that builds the rows simply increments $i without considering colspan settings in the header. This causes a misalignment of the header to the data columns when applying the vertical striping. Basically the "active" class shows up one column early on every column after a header column of colspan 2.
Suggested fix
Starting at line 2107
Issue queue
@jgreep, improvements are very welcome in the Drupal issue queue. Please search if the problem has already been reported. If not, create a new one. Be aware though that things will have to be fixed in Drupal 8 first before they can be backported to Drupal 7.