Drupal - Dynamic select list in the form (dependent dropdown)

You can use Ajax to accomplish this. Drupal 7 has good Ajax support now. On your first select list (city) you'll need to add Ajax information. Then, the second select list can be populated based on the information in the first. You can also even hide the second select list until an option in the first is selected, and I'll explain how to do that in a bit. First, to set up the basic form:

$form['city'] = array(
  '#type' => 'select',
  '#title' => t('City'),
  '#options' => $options,
  '#ajax' => array(
    'event' => 'change',
    'wrapper' => 'squadron-wrapper',
    'callback' => 'mymodule_ajax_callback',
    'method' => 'replace',
  ),
);
$form['squadron_wrapper'] = array('#prefix' => '<div class="squadron-wrapper">', '#suffix' => '</div>');
$form['squadron_wrapper']['squadron'] = array(
  '#type' => 'select',
  '#title' => t('Squadron'),
  '#options' => $squadron_options,
);

This is just the basic setup of the elements. Now you'll need a way to determine what options should go in squadron. First you need to make your Ajax callback identified in 'city' select list. In most cases you can just return the element that wraps the ajax element, in this case $form.

function mymodule_ajax_callback($form, $form_state) {
  return $form;
}

Now, when the 'city' select list changes it will rebuild the squadron-wrapper part of the form. Your 'city' value will now be in $form_state['values']. So, when the form is rebuilt we need to determine what options to give to the select list based on the value of 'city'.

// Get the value of the 'city' field.
$city = isset($form_state['values']['city']) ? $form_state['values']['city'] : 'default';
switch ($city) {
  case 'default':
    // Set default options.
    break;
  case 'losangeles':
    // Set up $squadron_options for los angeles.
    break;
}

// If you want to hide the squadron select list until a city is
// selected then you can do another conditional.
if ($city !== 'default') {
  $form['squadron_wrapper']['squadron'] = array(
    '#type' => 'select',
    '#title' => t('Squadron'),
    '#options' => $squadron_options,
  );
}

Many thanks to jordojuice above. With his help I managed to find a solution. I also refered to the example at http://public-action.org/content/drupal-7-form-api-dependent-lists-and-ajax-form-submission. I eventually used the code below which worked in a custom module. For some reason I couldn't find any of my values in the $form_state values, but was able to find them in $form. Finally, when I tested, I was getting an error message that Drupal had detected an illegal choice in the drop-down. I got round this by commenting out line 1290 in form.inc:

form_error($elements, $t('An illegal choice has been detected. Please contact the site administrator.'));

The final code I used was:

<?php

function sappers_squadron_form_work_history_node_form_alter(&$form, &$form_state) {     
        //echo '<pre>';
        //print_r ($form);
        //echo '</pre>';

        $squadron_options = array();

        if(isset($form['field_wkhist_city']['und']['#default_value'][0])) {
            $city = $form['field_wkhist_city']['und']['#default_value'][0];
        }
        else {
            $city = 0;
        }

        $squadron_options = sappers_squadron_squadrons($city);

        $form['field_wkhist_city']['und']['#ajax'] = array(
            'event' => 'change',
            'wrapper' => 'squadron-wrapper',
            'callback' => 'sappers_squadron_ajax_callback',
            'method' => 'replace',
        );

        $form['field_squadron']['und']['#prefix'] = '<div id="squadron-wrapper">';
        $form['field_squadron']['und']['#suffix'] = '</div>';
        $form['field_squadron']['und']['#options'] = $squadron_options;
}


function sappers_squadron_ajax_callback($form, $form_state) {   
    $city = $form['field_wkhist_city']['und']['#value'];

    $form['field_squadron']['und']['#options'] = sappers_squadron_squadrons($city);

    return $form['field_squadron'];
}


function sappers_squadron_squadrons($city) {
    $nodes = array();

    $select = db_query("SELECT node.title AS node_title, node.nid AS nid FROM  {node} node INNER JOIN {taxonomy_index} taxonomy_index ON node.nid = taxonomy_index.nid WHERE (( (node.status = '1') AND (node.type IN  ('squadron')) AND (taxonomy_index.tid = $city) )) ORDER BY node_title ASC");

    $nodes[]="";

    foreach ($select as $node) {
            $nodes[$node->nid] = $node->node_title;
    }

    return $nodes;
}

?>

put the line of code i.e
$nodes[''] = '- None -'; after

 $nodes = array();

in ur sappers_squadron_squadrons function and that will solve your error

form_error($elements, $t('An illegal choice has been detected. Please contact the site administrator.'));

Tags:

Forms

Ajax

7