Skip to main content

Multi-dependent select elements in Drupal 7 using ajax

Recently I needed to modify a Drupal 7 node form to have two drop down select elements populate based upon a third select element's choice. I have altered select elements in the past to have a single dependency, but never have I made one element control the content of two different elements.

To start, I made the first element control the second (the old familiar way):

I need the selection in field_dropdown_1 to dictate what appears in the list for field_dropdown_2 and field_dropdown_3.

To start, I used hook_form_alter() to add the #ajax functionality to field_dropdown_1 like so:

  1. $form['field_dropdown_1'][LANGUAGE_NONE]['#ajax'] = array(
  2.     'callback' => 'my_custom_callback',
  3.     'wrapper' => 'my-wrapper-div-1',
  4.   );
  5.  
  6. /**
  7.  Logic to get the options of field_dropdown_2 would go here.
  8. **/

Next, I added my callback function for the ajax element:

  1. function my_custom_callback ($form, $form_state) {
  2.   return $form['field_dropdown_2'];
  3. }

The code above gave me a single dependent select element. Now, how do we add the second dropdown?

Solution

After reading the form API reference regarding the #ajax property: https://api.drupal.org/api/drupal/developer!topics!forms_api_reference…, I discovered that the ajax callback expects HTML OR an array of ajax commands to execute. This discovery led me to the ajax_command_replace() function: https://api.drupal.org/api/drupal/includes!ajax.inc/function/ajax_comma….

So, as it turns out, to modify two select's with one ajax call we just needed to modify our custom callback function to return ajax commands like this:

  1. $result = array(
  2.     '#type' => 'ajax',
  3.     '#commands' => array(
  4.       ajax_command_replace('#my-wrapper-div-1', drupal_render($form['field_dropdown_2'])),
  5.       ajax_command_replace('#my-wrapper-div-2', drupal_render($form['field_dropdown_3'])),
  6.     ),
  7.   );
  8.   return $result;

This change in the callback function returns two ajax replace commands, one for field_dropdown_2 and a second for field_dropdown_3.

Thanks to these two comments for helping me get the callback correct:
https://api.drupal.org/comment/50903#comment-50903
https://api.drupal.org/comment/51178#comment-51178


Comments