ajax callback add more on a select field I am trying to implement a "add x" on a select field but it doesn't seem to work.

I've tried to follow this example but they use a submit for that.

$form['myfield'] = array(
    '#type' =&gt; 'select',
    '#options' =&gt; $optionsServer,
    '#ajax' =&gt; array(
        'callback' =&gt; 'ajax_select_change',
        'wrapper' =&gt; 'names-fieldset-wrapper',
        'method' =&gt; 'replace',
        'effect' =&gt; 'fade',
    ),
);

$form['#tree'] = TRUE;
if (empty($form_state['num_names'])) {
   $form_state['num_names'] = 1;
}
$form['myfieldset'] = array(
        '#type' =&gt; 'fieldset',
        '#title' =&gt; t('myfieldset'),
        '#prefix' =&gt; '&lt;div id="names-fieldset-wrapper"&gt;',
        '#suffix' =&gt; '&lt;/div&gt;',
    );
for ($i = 0; $i &lt; $form_state['num_names']; $i++) {
   $form['myfieldset']['field'.$i] = array(
       '#type' =&gt; 'textfield',
       '#title' =&gt; t('field'),
       '#size' =&gt; 60,
       '#required' =&gt; TRUE,
   );
}

function ajax_select_change($form, &amp;$form_state){
    //$form_state['num_names'] is used to create x new textfield
    $form_state['num_names'] = $form_state['values']['myfield'];
    //rebuild this form to get the new count
    $form_state['rebuild'] = TRUE;
    //change the fieldset containing the code to build textfield
    return $form['myfieldset'];
}


Is it doable?
I can try to create a button then trigger it when I change the select value but this is clearly a crappy hack.

Any idea?

EDIT: I find out some solution:

function my_form($form, $form_state){
    $form['container']['myField1'] = array(
        '#type' =&gt; 'select',
        '#options' =&gt; $optionsField1,
        //don't forget the $form_state['values']['container']['myField1'] as default, it will keep the same value after the rebuild
        '#default_value' =&gt; isset($form_state['values']['container']['myField1']) ? $form_state['values']['container']['myField1'] : $form_state['num_names'] ,
        '#ajax' =&gt; array(
            'callback' =&gt; 'ajax_select_change',
        ),
    );
}


function ajax_select_change($form, $form_state){
    $new_state = array();
    $new_state['build_info'] = $form_state['build_info'];
    $new_state['rebuild'] = TRUE;
    $new_state['values'] = $form_state['values'];
    $new_state += form_state_defaults();

    $new_form_array = drupal_rebuild_form('my_form', $new_state);
    $new_form = drupal_render($new_form_array);

    $commands = array();
    //reload form
    $commands[] = ajax_command_html('#formId', $new_form);
    //change inside Id #price
    $commands[] = ajax_command_replace('#price', drupal_render($form['container']['myField2']));
    return array('#type' =&gt; 'ajax', '#commands' =&gt; $commands);
}


EDIT 2: see the proper solution below (in the comment), much more simple and make more sense!
After an AJAX submit by a select or some similar not submit element the Form API rebuilds de form if no validate errors are found. See drupal_process_form() where this is stated in the inline comments:    


// However, for forms that have not been fully executed (e.g., Ajax
// submissions triggered by non-buttons), there is no submit handler to set
// $form_state['rebuild']. It would not make sense to redisplay the
// identical form without an error for the user to correct, so we also
// rebuild error-free non-executed forms, regardless of
// $form_state['rebuild'].



Your code is not working because you update your number of elements in the callback function in this line:

$form_state['num_names'] = $form_state['values']['myfield'];


The callback function is executed after all form processing so your modifications are done too late. In fact, callback function should only return the response, no modifications on the form should be done here.

Try something like this:

$form['myfield'] = array(
    '#type' =&gt; 'select',
    '#options' =&gt; $optionsServer,
    '#ajax' =&gt; array(
        'callback' =&gt; 'ajax_select_change',
        'wrapper' =&gt; 'names-fieldset-wrapper',
        'method' =&gt; 'replace',
        'effect' =&gt; 'fade',
    ),
);

$form['#tree'] = TRUE;
if (empty($form_state['num_names'])) {
   $form_state['num_names'] = 1;
}
else {
  // If there's is value in myfield update number of available names elems.
  $form_state['num_names'] = $form_state['values']['myfield'];
}


$form['myfieldset'] = array(
        '#type' =&gt; 'fieldset',
        '#title' =&gt; t('myfieldset'),
        '#prefix' =&gt; '&lt;div id="names-fieldset-wrapper"&gt;',
        '#suffix' =&gt; '&lt;/div&gt;',
    );
for ($i = 0; $i &lt; $form_state['num_names']; $i++) {
   $form['myfieldset']['field'.$i] = array(
       '#type' =&gt; 'textfield',
       '#title' =&gt; t('field'),
       '#size' =&gt; 60,
       '#required' =&gt; TRUE,
   );
}

function ajax_select_change($form, &amp;$form_state){
    return $form['myfieldset'];
}