How to dynamically populate select options? I'm trying to build an admin form for a module, using system_settings_form().

I want the users to be able to select sub-options, from a list that is dynamically generated depending on the main option.

For example

$main_options = array('foo','bar');
$sub_options['foo'] = array('foolish','football','foodstuff');
$sub_options['bar'] = array('barley','baroque','barbarian');

$form = array();

$form['main_option'] = array(
    '#type' =&gt; 'select',
    '#options' =&gt; $main_options,
);

$form['sub_option'] = array(
    '#type'  =&gt; 'select',
    '#options' =&gt; $sub_options[SOMEHOW USE THE SELECTED VALUE OF main_option AS INDEX],
);

return system_settings_form($form);


So I would expect sub_option to be unpopulated the first time the form is called, and then populated as soon as the user populates main_option.

Is this possible?

Update

Thanks for the advice re Ajax. I looked up https://www.drupal.org/node/752056 and this is what I've built: here the values in olt_test need to change based on the value selected for olt_provider.

  $form['olt_provider'] = array(
    '#type' =&gt; 'select',
    '#title' =&gt; t('Provider'),
    '#options' =&gt; variable_get('providers'),
    '#ajax' =&gt; array(
      'callback' =&gt; 'olt_provider_select_callback',
      'wrapper' =&gt; 'tests-div',
      'method' =&gt; 'replace',
      'effect' =&gt; 'fade',
    ),
  );

  $form['olt_test'] = array(
    '#type' =&gt; 'select',
    '#title' =&gt; t('Test'),
    '#prefix' =&gt; '&lt;div id="tests-div"&gt;',
    '#options' =&gt; array(''),
  );


and in olt_provider_select_callback() I have

  function olt_provider_select_callback($form, $form_state) {

  $new_options_value = [new value calculation snipped]  

  $form['olt_test'] = array(
    '#type' =&gt; 'select',
    '#title' =&gt; t('Test'),
    '#prefix' =&gt; '&lt;div id="tests-div"&gt;',
    '#options' =&gt; $new_options_value,
  );

  return $form['olt_test'];
}


The problem I'm now seeing is that the Ajax only fires on the first time the olt_provider select box is clicked - subsequent clicks don't fire. Any thoughts?

The problem I'm now seeing is that although the olt_test dropdown is correctly updated via Ajax, this replacement value is not saved on form submission. Any thoughts?

Final Update - My form is working correctly now. The data was being saved on form submission, but I needed to add some more code to retrieve the saved data and display the default values when the form was loaded.
As said before you could make use of Form APIs #states to display one element only after a certain input to another form element has been made. In your case you'd maybe go with two additional select lists, both initially hidden. Check form_examples_states_form() for more information.

$form['main'] = array(
  '#type' =&gt; 'select',
  // ...
);
$form['sub_a'] = array(
  '#type' =&gt; 'select',
  // ...
  '#states' =&gt; array(
    'visible' =&gt; array(
      ':input[name="main"]' =&gt; array('value' =&gt; 'foo'),
    ),
  ),
);
$form['sub_b'] = array(
  '#type' =&gt; 'select',
  // ...
  '#states' =&gt; array(
    'visible' =&gt; array(
      ':input[name="main"]' =&gt; array('value' =&gt; 'bar'),
    ),
  ),
);