1

Started with the example here: https://api.drupal.org/api/examples/ajax_example!ajax_example.module/function/ajax_example_dependent_dropdown/7

However, I then wanted to add a third option that was depended on the first two (which is not in the example given)

The problem I first ran into was that when I updated the first dropdown it would update the second, but not the third.

So I changed the callbacks from

function ajax_example_dependent_dropdown_callback1($form, $form_state) {
  return $form['dropdown_second'];
}

and

function ajax_example_dependent_dropdown_callback2($form, $form_state) {
  return $form['dropdown_third'];
}

to

function _ajax_example_dependent_dropdown_callback1($form, $form_state) {
  $commands[] = ajax_command_insert('#dropdown-second-replace', drupal_render($form['dropdown_second']));
  $commands[] = ajax_command_insert('#dropdown-third-replace', drupal_render($form['dropdown_third']));
  return array('#type' => 'ajax', '#commands' => $commands);
}

function ajax_example_dependent_dropdown_callback2($form, $form_state) {
  $commands[] = ajax_command_insert('#dropdown-second-replace', drupal_render($form['dropdown_second']));
  $commands[] = ajax_command_insert('#dropdown-third-replace', drupal_render($form['dropdown_third']));
  return array('#type' => 'ajax', '#commands' => $commands);
}

Which got me most of the way, but I still have one problem left. It seems that when I update the first dropdown, it updates the options in the second box but doesn't send the updated value into my options function to get the new options for the third box.

Here is my code:

function cquiz_create_exam($form, &$form_state) {
  $subjects = _cquiz_get_subjects();
  $selected = isset($form_state['values']['dropdown_first']) ? $form_state['values']['dropdown_first'] : $subjects[key($subjects)];

  $form['dropdown_first'] = array(
    '#type' => 'select',
    '#title' => 'Select Subject',
    '#options' => array_unique($subjects),
    '#default_value' => $selected,
    '#ajax' => array(
      'callback' => '_cquiz_create_exam_callback_first',
      'wrapper' => 'dropdown-second-replace',
    ),
  );

  $type = _cquiz_get_type($selected);
  $selected2 = isset($form_state['values']['dropdown_second']) ? $form_state['values']['dropdown_second'] : $type[key($type)];

  $form['dropdown_second'] = array(
    '#type' => 'select',
    '#title' => t('Exam Type'),
    '#prefix' => '<div id="dropdown-second-replace">',
    '#suffix' => '</div>',
    '#options' => _cquiz_get_type($selected),
    '#default_value' => isset($form_state['values']['dropdown_second']) ? $form_state['values']['dropdown_second'] : '',
    '#ajax' => array(
      'callback' => '_cquiz_create_exam_callback_second',
      'wrapper' => 'dropdown-third-replace',
    ),
  );

  $form['dropdown_third'] = array(
    '#type' => 'select',
    '#title' => t('Number of Questions'),
    '#prefix' => '<div id="dropdown-third-replace">',
    '#suffix' => '</div>',
    '#options' => _cquiz_get_number($selected, $selected2),
    '#default_value' => isset($form_state['values']['dropdown_third']) ? $form_state['values']['dropdown_third'] : '',
  );

  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Submit'),
  );
  return $form;
}

In the $form['dropdown_third'] section you can see that the options are defined by another function. That function doesn't get redone after changing the first drop down box. How do I get it to reload those options using the new select values?

1

Not totally sure, but setting $form_state['rebuild'] = TRUE in your submit or validation handler may help here.

This is the key function for making multi-step forms advance from step to step. It is called by drupal_process_form() when all user input processing, including calling validation and submission handlers, for the request is finished. If a validate or submit handler set $form_state['rebuild'] to TRUE, and if other conditions don't preempt a rebuild from happening, then this function is called to generate a new $form, the next step in the form workflow, to be returned for rendering.

https://api.drupal.org/api/drupal/includes!form.inc/function/drupal_rebuild_form/7

Another option would be to replace the entire form on in your AJAX callback. So essentially you'll specify a #prefix and #suffix for the entire form and then use that prefix element id in your $form['dropdown_first/second']['#ajax']['wrapper']. Your callback will look something like this:

function ajax_example_dependent_dropdown_callback($form, $form_state) {
  ...
  return $form;
}

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.