Hello all
I am encouring a strange problem , maybe I am doing something wrong, but I followed some example modules to build my own module functions.
The argument is AJAX and add dynamically form elements, more precisely I need to add multiple form fields on a form, but they aren't simple form element, rather they are a set of fields , a kind of fieldset.
So by clicking an "Add new field" button I need to make a new instance of a fieldset with different fields.Here my code:


/**
 *  This function generate the new field tree structure
 */
function my_module_dynamic_field($i) {
  $form=array();
  [...............]
  $form['my_own_field_text_A'][$i]=array(
    '#type'=>'textfield'
  );
  $form['my_own_field_weight_B'][$i] = array(
    '#type' => 'weight',
    '#title_display' => 'invisible'
  );
  [....................]
  return $form;
}

/**
 *  This function alters an existing form adding a new section of fields of my own
 */
function my_module_alter_form(&$form, &$form_state) {

  $form['ajax_container'] = array(
    '#type'   => 'fieldset',
    '#title'  => t("Dynamic fields"),
    '#weight' => $form['body']['#weight'] + 1,
    '#prefix' => '<div id="ajax_wrapper">',
    '#suffix' => '</div>'
  );
  $form['ajax_container']['items']['#tree']=TRUE;
  
  [..................]

  $form['ajax_container']['add'] = array(
    '#type'   => 'submit',
    '#value'  => t('Add new field'),
    '#submit' => array('my_module_ajax_field_submit'),
    '#ajax'   => array(
      'callback'=> 'my_module_ajax_callback',
      'wrapper' => 'ajax_wrapper',
      'effect'  => 'fade',
    )
  );
  if (empty($form_state['n_items'])) {
    $form_state['n_items'] = 1;
  }
  
  if (isset($form_state['values']['add'])) {
    $i = $form_state['n_items'];
    $form['ajax_container']['items'] += (array)my_module_dynamic_field($i);
  } 
}

function my_module_ajax_field_submit($form, &$form_state) {
  $form_state['n_items']++;
  $form_state['rebuild'] = TRUE;
}

function my_module_ajax_callback($form, $form_state) {
  return $form['ajax_container'];
}

The problem is that this code doesn't work correctly, it just add and replace the previous form content with the new field, it doesn't add to the form tree structure the new fields. It seems when I submit the form, that the form elements I have added previously are not registered on the form structure when submitting.
Do you know what I mean?
Hope you understand me because my english is not my native language.
Thanks in advance
Greetings

Comments

Jaypan’s picture

You need to build the previously submitted elements as well as add the new elements. For example:

$form['something']['#tree'] = TRUE;
$i = 0;
if(isset($form_state['values']['something']))
{
  // The form has been submitted, so this is part of the #ajax response
  // so we loop through and re-build the previous values
  while(isset($form_state['values']['something'][$i]))
  {
    $form['something'][$i] = array
    (
      '#type' => 'textfield',
      '#title' => t('My element !number', array('!number' => $i + 1)),
      '#default_value' => $form_state['values']['something'][$i],
    );
    $i++;
  }
}
// Now the original form elements have been rebuilt (if they existed)
// and we add an empty element. This happens whether or not any
// previous form elements existed. 
$form['something'][$i] = array
(
  '#type' => 'textfield',
  '#title' => t('My element !number', array('!number' => $i + 1)),
);

As you can see, when the form is initially built ($form_state['values']['something'] is not set), then the element with an index of 0 is the only thing inserted in the form. But when the form has been submitted
through #ajax, it builds a form element for each submitted value, then adds a final element afterwards.

fabio88’s picture

Thank you very much, it worked !
I thought when setting $form_rebuild to TRUE on submit callback, it would have saved automatically the previous form fields added, but now I see I needed to re-add them manually by form values!
Again thanks!
Greets