Skip to main content

Drupal 7: Ajax Forms with Multiple Callbacks.

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:

  1.   $form['company']['company_branches'] = array(
  2.     '#type' => 'select',
  3.     '#title' => t('Do you have additional branch locations?'),
  4.     '#options' => array('no' => 'No', 'yes' => 'Yes'),
  5.     '#ajax' => array(
  6.       'callback' => 'MYMODULE_membership_form_add_location',
  7.       'wrapper' => 'additional-branches',
  8.       'effect' => 'fade',
  9.       'method' => 'replace',
  10.     ),
  11.   );
  12.   // Container for the additional branches.
  13.   $form['company']['additional_branches'] = array(
  14.     '#prefix' => '<div id="additional-branches">',
  15.     '#suffix' => '</div>',
  16.     '#type' => 'fieldset',
  17.   );

Next I setup the standard Drupal ajax callback which looks like this:

  1.   function MYMODULE_membership_form_add_location($form, $form_state){
  2.     return $form['company']['additional_branches'];
  3.   }

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:

  1. /**
  2.  * 'append' callback.
  3.  *
  4.  * @see ajax_command_append()
  5.  */
  6. function ajax_example_advanced_commands_append_callback($form, $form_state) {
  7.   $selector = '#append_div';
  8.  
  9.   $commands = array();
  10.   $commands[] = ajax_command_append($selector, "Stuff...");
  11.   $commands[] = ajax_command_replace("#append_status", "<div id='append_status'>Updated append_command_example " . date('r') . "</div>");
  12.   return array('#type' => 'ajax', '#commands' => $commands);
  13. }

Using the $commands array from the example module above, I modified my function to look like this:

  1. function MYMODULE_membership_form_add_location($form, $form_state){
  2.   $selector = '#estimate';
  3.  
  4.   $commands = array();
  5.   $commands[] = ajax_command_html($selector, "UPDATED HTML HERE");
  6. /**
  7. * The line below is replacing the original return statement. Be sure to run the form through drupal_render to make this work.
  8. */
  9.   $commands[] = ajax_command_replace("#additional-branches", drupal_render($form['company']['additional_branches']));
  10.   return array('#type' => 'ajax', '#commands' => $commands);
  11.  
  12. /**
  13. * This is the original callback return statement that just returned the part of the form you wanted updated
  14. */
  15.   //return $form['company']['additional_branches'];
  16. }

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.


Comments