Elements
If you are familiar with the Drupal forms API you know the concept of form elements as the basic building blocks of any form. Drupal provides several types of elements, some rather straightforward (#type textfield), some more advanced (#type password_confirm).
It is also possible to define custom form elements that enable you to implement complex widgets with ease.
At the moment, the focus of Elements is the tableselect widget. It 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.
Example scaffolding
You can use the following code to create an example.module which you can use to experiment with the examples in this guide.
// example.module
function example_menu($maycache) {
if ($maycache) {
'path' => 'scratch/elements',
'access' =
> user_access('administer site configuration'),
'title' =
> t('Elements'),
'callback' => 'drupal_get_form',
'callback arguments' =
> array('example_elements_form'),
);
return $items;
}
}
; example.info
name = "Example"
description = "Quick scratch module."
Comboselect element
The comboselect element has not yet been included in Elements. You can follow its development at #268424.
The comboselect written by John Morahan gives you a select type element with an 'Other' option. When the user chooses this option; a textfield appears.

Create a simple comboselect element
function example_elements_form() {
'one' =
> t('First Option'),
'two' =
> t('Second Option'),
);
'#type' => 'comboselect',
'#title' =
> t('Example'),
'#default_options' => $options,
);
'#type' => 'submit',
);
return $form;
}


Change the 'Other' option
function example_elements_form() {
'one' =
> t('First Option'),
'two' =
> t('Second Option'),
);
'#type' => 'comboselect',
'#title' =
> t('Example'),
'#required' => TRUE,
'#default_options' => $options,
'#other' =
> t('None of the above, but'),
);
'#type' => 'submit',
);
return $form;
}
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:

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:

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.