function ajax_example_dependent_dropdown_degrades

Dropdown form based on previous choices.

A form with a dropdown whose options are dependent on a choice made in a previous dropdown.

On changing the first dropdown, the options in the second are updated. Gracefully degrades if no javascript.

A bit of CSS and javascript is required. The CSS hides the "add more" button if javascript is not enabled. The Javascript snippet is really only used to enable us to present the form in degraded mode without forcing the user to turn off Javascript. Both of these are loaded by using the #attached FAPI property, so it is a good example of how to use that.

The extra argument $no_js_use is here only to allow presentation of this form as if Javascript were not enabled. ajax_example_menu() provides two ways to call this form, one normal ($no_js_use = FALSE) and one simulating Javascript disabled ($no_js_use = TRUE).

Related topics

1 string reference to 'ajax_example_dependent_dropdown_degrades'
ajax_example_menu in ajax_example/ajax_example.module
Implements hook_menu().

File

ajax_example/ajax_example_graceful_degradation.inc, line 40

Code

function ajax_example_dependent_dropdown_degrades($form, &$form_state, $no_js_use = FALSE) {
    // Get the list of options to populate the first dropdown.
    $options_first = _ajax_example_get_first_dropdown_options();
    // If we have a value for the first dropdown from $form_state['values'] we use
    // this both as the default value for the first dropdown and also as a
    // parameter to pass to the function that retrieves the options for the
    // second dropdown.
    $selected = isset($form_state['values']['dropdown_first']) ? $form_state['values']['dropdown_first'] : key($options_first);
    // Attach the CSS and JS we need to show this with and without javascript.
    // Without javascript we need an extra "Choose" button, and this is
    // hidden when we have javascript enabled.
    $form['#attached']['css'] = array(
        drupal_get_path('module', 'ajax_example') . '/ajax_example.css',
    );
    $form['#attached']['js'] = array(
        drupal_get_path('module', 'ajax_example') . '/ajax_example.js',
    );
    $form['dropdown_first_fieldset'] = array(
        '#type' => 'fieldset',
    );
    $form['dropdown_first_fieldset']['dropdown_first'] = array(
        '#type' => 'select',
        '#title' => 'Instrument Type',
        '#options' => $options_first,
        '#attributes' => array(
            'class' => array(
                'enabled-for-ajax',
            ),
        ),
        // The '#ajax' property allows us to bind a callback to the server whenever
        // this form element changes. See ajax_example_autocheckboxes and
        // ajax_example_dependent_dropdown in ajax_example.module for more details.
'#ajax' => array(
            'callback' => 'ajax_example_dependent_dropdown_degrades_first_callback',
            'wrapper' => 'dropdown-second-replace',
        ),
    );
    // This simply allows us to demonstrate no-javascript use without
    // actually turning off javascript in the browser. Removing the #ajax
    // element turns off AJAX behaviors on that element and as a result
    // ajax.js doesn't get loaded. This is for demonstration purposes only.
    if ($no_js_use) {
        unset($form['dropdown_first_fieldset']['dropdown_first']['#ajax']);
    }
    // Since we don't know if the user has js or not, we always need to output
    // this element, then hide it with with css if javascript is enabled.
    $form['dropdown_first_fieldset']['continue_to_second'] = array(
        '#type' => 'submit',
        '#value' => t('Choose'),
        '#attributes' => array(
            'class' => array(
                'next-button',
            ),
        ),
    );
    $form['dropdown_second_fieldset'] = array(
        '#type' => 'fieldset',
    );
    $form['dropdown_second_fieldset']['dropdown_second'] = array(
        '#type' => 'select',
        '#title' => $options_first[$selected] . ' ' . t('Instruments'),
        '#prefix' => '<div id="dropdown-second-replace">',
        '#suffix' => '</div>',
        '#attributes' => array(
            'class' => array(
                'enabled-for-ajax',
            ),
        ),
        // When the form is rebuilt during processing (either AJAX or multistep),
        // the $selected variable will now have the new value and so the options
        // will change.
'#options' => _ajax_example_get_second_dropdown_options($selected),
    );
    $form['dropdown_second_fieldset']['submit'] = array(
        '#type' => 'submit',
        '#value' => t('OK'),
        // This class allows attached js file to override the disabled attribute,
        // since it's not necessary in ajax-enabled form.
'#attributes' => array(
            'class' => array(
                'enabled-for-ajax',
            ),
        ),
    );
    // Disable dropdown_second if a selection has not been made on dropdown_first.
    if (empty($form_state['values']['dropdown_first'])) {
        $form['dropdown_second_fieldset']['dropdown_second']['#disabled'] = TRUE;
        $form['dropdown_second_fieldset']['dropdown_second']['#description'] = t('You must make your choice on the first dropdown before changing this second one.');
        $form['dropdown_second_fieldset']['submit']['#disabled'] = TRUE;
    }
    return $form;
}