Drupal 7: Ajax Forms with Multiple Callbacks.

Profile picture for user Phil Frilling
By Phil Frilling, 6 March, 2012
Today I needed to create an ajax powered form using Drupal 7, the caveat being that I needed one user action to perform multiple ajax actions to different sections of the form. To begin, my form element with the ajax looks like this:

  $form['company']['company_branches'] = array(
    '#type' => 'select',
    '#title' => t('Do you have additional branch locations?'),
    '#options' => array('no' => 'No', 'yes' => 'Yes'),
    '#ajax' => array(
      'callback' => 'MYMODULE_membership_form_add_location',
      'wrapper' => 'additional-branches',
      'effect' => 'fade',
      'method' => 'replace',
    ),
  );
  // Container for the additional branches.
  $form['company']['additional_branches'] = array(
    '#prefix' => '',
    '#suffix' => '',
    '#type' => 'fieldset',
  );
Next I setup the standard Drupal ajax callback which looks like this:

  function MYMODULE_membership_form_add_location($form, $form_state){
    return $form['company']['additional_branches'];
  }
Now that I had the standard setup working correctly, I needed to figure out how to have this callback function act on two separate areas of the form. After consulting the ajax_example.module, I found the ajax_example_advanced.inc file. Specifically, I used the following function as my reference:

/**
 * 'append' callback.
 *
 * @see ajax_command_append()
 */
function ajax_example_advanced_commands_append_callback($form, $form_state) {
  $selector = '#append_div';

  $commands = array();
  $commands[] = ajax_command_append($selector, "Stuff...");
  $commands[] = ajax_command_replace("#append_status", "Updated append_command_example " . date('r') . "");
  return array('#type' => 'ajax', '#commands' => $commands);
}
Using the $commands array from the example module above, I modified my function to look like this:

function MYMODULE_membership_form_add_location($form, $form_state){
  $selector = '#estimate';

  $commands = array();
  $commands[] = ajax_command_html($selector, "UPDATED HTML HERE");
/**
* The line below is replacing the original return statement. Be sure to run the form through drupal_render to make this work.
*/
  $commands[] = ajax_command_replace("#additional-branches", drupal_render($form['company']['additional_branches']));
  return array('#type' => 'ajax', '#commands' => $commands);
  
/**
* This is the original callback return statement that just returned the part of the form you wanted updated
*/
  //return $form['company']['additional_branches'];
}
The key to getting this to work is to make sure you run the form element through drupal_render in the ajax_command_replace function. That's it, you can act on multiple areas of your form while only using one callback function and one action in the form.