Using the Drupal 7 tableselect form field, is there a way to attach javascript events to the checkboxes?

I am trying to build a custom pricing table that lets you add different options, which modifies the displayed total. When checking off an option, I need to pass the value through AJAX and return a new total price. Not sure though how to attach events.


The '#ajax' property handling of the tableselect element is broken at the moment. The approach shown by mrryanjohnston should work in theory, but I can confirm Kevins observation that it does not do so for checkboxes ('#multiple' = true). It does work for radio buttons, though ('#multiple' = false). The issue is reported as a bug in the meantime.

To me this seems to be just an oversight - looking at form_process_tableselect() shows that the line which passes the '#ajax' property on to the created child elements is only present in the 'radios' related else part of the if clause, but absent for the default checkbox creation part. Adding the line there fixes the problem on first sight - not sure if it has some negative effects and was left out on purpose, but I doubt that.

As a workaround to avoid patching core, you can register an additional #process callback, to be invoked after the default one:

$form['some_tableselect'] = array(
  '#type' => 'tableselect',
  '#header' => array('one', 'two'),
  '#options' => your_module_function_creating_options(),
  // Kludge/workaround for broken #ajax handling for checkboxes,
  // register an additional process callback:
  '#process' => array('form_process_tableselect', 'your_module_tableselect_process_callback'),

Then in your new callback, you add the ajax property to the created checkboxes directly:

function your_module_tableselect_process_callback($form_element) {
  foreach (element_children($form_element) as $child_key) {
    if ('checkbox' == $form_element[$child_key]['#type']) {
      // Add ajax behavior as desired
      $form_element[$child_key]['#ajax'] = array(
        'callback' => 'your_module_ajax_callback',
        'wrapper' => 'some-wrapper-id',

  return $form_element;

Note that this only covers the individual checkboxes per line - the 'select all' checkbox in the header gets added via JavaScript later on, and can not be 'fixed' like this :/


I'm pretty sure this is quite doable with the #ajax key in a renderable array. From http://drupal.org/node/752056:

 * AJAX-enabled select element causes replacement of a set of checkboxes
 * based on the selection.
function ajax_example_autocheckboxes($form, &$form_state) {

  $default = !empty($form_state['values']['howmany']) ? $form_state['values']['howmany'] : 1;

  $form['howmany_select'] = array(
    '#title' => t('How many checkboxes do you want?'),
    '#type' => 'select',
    '#options' => array(1 => 1, 2 => 2, 3 => 3, 4 => 4),
    '#default_value' => $default,
    '#ajax' => array(
      'callback' => 'ajax_example_autocheckboxes_callback',
      'wrapper' => 'checkboxes-div',
      'method' => 'replace',
      'effect' => 'fade',


  $form['checkboxes_fieldset'] = array(
    '#title' => t("Generated Checkboxes"),
    // The prefix/suffix provide the div that we're replacing, named by
    // #ajax['wrapper'] above.
    '#prefix' => '<div id="checkboxes-div">',
    '#suffix' => '</div>',
    '#type' => 'fieldset',
    '#description' => t('This is where we get automatically generated checkboxes'),

  // Complete example below!

Basically, define what function is going to be triggered by what action (in this case, a checkbox toggle). With the above code, define a function such that its signature is ajax_example_autocheckboxes_callback. Voila.

  • This works for common fields like select, but tableselect does not seem to do anything, even though its listed as supporting the #ajax property.
    – Kevin
    Feb 8 '12 at 21:33

@Kevin try this

function a_form($form, &$formstate){
  $header = array
    'name' => 'name',
    'surname' => 'surname',
    'citizen_id' => 'citizen id',

  $options['1'] = array(
    'name' => '1name',
    'surname' => '1surname',
    'citizen_id' => '1citi',

  $options['2'] = array(
    'name' => '2name',
    'surname' => '2surname',
    'citizen_id' => '2citi',

  $form['tableselect_field'] = array(
    '#type' => 'tableselect',
    '#header' => $header,
    '#options' => $options,
    '#multiple' => FALSE,
    '#ajax' => array(
      'callback' => 'an_example_callback',
      'wrapper' => 'a-div',
      'method' => 'replace',
      'effect' => 'fade',

  $form['ajax_div'] = array(
    '#type' => 'markup',
    '#prefix' => '<div id="a-div">',
    '#markup' => date('y-m-d h:i:s'),
    '#suffix' => '</div>',

  return $form;

function an_example_callback($form, $form_state) {
  return $form['ajax_div'];
  • This is what I have for my tableselect, but no ajax fires (checking Firebug)
    – Kevin
    Feb 10 '12 at 15:41

There is a new patch for ajax on tableselect checkboxes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.