Tableselect element

The form element tableselect provides a clean, easy way to create tables with one checkbox per row, multi-row selection and a select all checkbox, without making your code a complicated mess:

Update: This book is about the tableselect element provided by the Elements module for Drupal 5 and 6. See A new form element in Drupal core for a HOWTO on the new Drupal 7 form element.

A simple table

The basic properties of the tableselect element are #header which accepts an array of key => value pairs to generate the header from and #options, which receives an array of rows.

The basic structure looks like the following:

$header = array(
  'field1' => 'Title of field 1',
  'field2' => 'Title of field 2',
);

$options['some_unique_id'] = array(
  'field1' => 'Value of field 1',
  'field2' => 'Value of field 2',
);

The tableselect element relies on the keys to match columns with the appropriate header. The element will behave like the #checkboxes type. You'll get an array of values in your submit function, with the checked ones set to nonzero so you can array_filter them to get the checked rows.

function example_elements_form() {
  $form = array();

  $header = array(
    'title' => t('Title'),
    'author' => t('Author'),
  );

  $query = "SELECT n.nid, n.title, u.name FROM {node} n INNER JOIN {users} u ON n.uid = u.uid";
  $result = pager_query(db_rewrite_sql($query));

  while($partial_node = db_fetch_object($result)) {
    $options[$partial_node->nid] = array(
      'title' => check_plain($partial_node->title),
      'author' => check_plain($partial_node->name),
    );
  }

  if (!empty($options)) {
    $form['nodes'] = array(
      '#type' => 'tableselect',
      '#header' => $header,
      '#options' => $options,
    );

    $form['pager'] = array('#value' => theme('pager'));

    $form['submit'] = array(
      '#type' => 'submit',
      '#value' => t('Submit'),
    );

  }
  return $form;
}

Which results in:

Example table

Support for sortable tables

The tableselect element supports use with tablesort_sql. Simply modify the header to the format described in theme_table.

function example_elements_form() {
  $form = array();

  $header = array(
    'title' => array('field' => 'n.title', 'data' => t('Title')),
    'author' => array('field' => 'u.name', 'data' => t('Author')),
  );

  $query = "SELECT n.nid, n.title, u.name FROM {node} n INNER JOIN {users} u ON n.uid = u.uid". tablesort_sql($header);

  $result = pager_query(db_rewrite_sql($query));

  while($partial_node = db_fetch_object($result)) {
    $options[$partial_node->nid] = array(
      'title' => check_plain($partial_node->title),
      'author' => theme('username', $partial_node),
    );
  }

  if (!empty($options)) {
    $form['nodes'] = array(
      '#type' => 'tableselect',
      '#header' => $header,
      '#options' => $options,
    );

    $form['pager'] = array('#value' => theme('pager'));

    $form['submit'] = array(
      '#type' => 'submit',
      '#value' => t('Submit'),
    );

  }

  return $form;
}

Properties

#header
The table header, an array of field_key => title pairs or the format described for theme_table.
#options
The data displayed in the table. Nested array of id => array pairs where the array is an array of field_key => value pairs.
#multiple
Determines whether multiple values can be selected. Displays checkboxes when TRUE, radios when FALSE.
Default: TRUE
#advanced_select
Whether to provide advanced selection behaviour (SELECT ALL checkbox, SHIFT-select).
Default: TRUE - when #multiple is TRUE.
When #multiple is FALSE, always FALSE.
#default_value
Provide an array of id => x pairs for the ids that should be selected by default when #multiple is TRUE.
Provide the id as a scalar for the id that should be selected by default when #multiple is FALSE.