2

I am implementing a form and in that form it requires that two form element should be coming under one Add more button, so user can add any number of fields.

Here is the code which i am using to create a form.

function ajax_example_add_more($form, &$form_state, $no_js_use = FALSE) {
  $form['description'] = array(
    '#markup' => '<div>' . t('This example shows an add-more and a remove-last button. The <a href="!ajax">AJAX version</a> does it without page reloads; the <a href="!multistep">non-js version</a> is the same code but simulates a non-javascript environment, showing it with page reloads.',
      array('!ajax' => url('examples/ajax_example/add_more'), '!multistep' => url('examples/ajax_example/add_more_no_js')))
    . '</div>',
  );

  $form['#tree'] = TRUE;
  $form['names_fieldset'] = array(
    '#type' => 'fieldset',
    '#title' => t('People coming to the picnic'),
    '#prefix' => '<div id="names-fieldset-wrapper">',
    '#suffix' => '</div>',
  );
  if (empty($form_state['num_names'])) {
    $form_state['num_names'] = 1;
  }
  for ($i = 0; $i < $form_state['num_names']; $i++) {
    $form['names_fieldset']['name'][$i] = array(
      '#type' => 'textfield',
      '#title' => t('Name'),
    );
    $form['names_fieldset']['surname'][$i] = array(
            '#type' => 'textfield',
            '#title' => t('SurName'),
    );
  }
  $form['names_fieldset']['add_name'] = array(
    '#type' => 'submit',
    '#value' => t('Add one more'),
    '#submit' => array('ajax_example_add_more_add_one'),
    '#ajax' => array(
      'callback' => 'ajax_example_add_more_callback',
      'wrapper' => 'names-fieldset-wrapper',
    ),
  );
  if ($form_state['num_names'] > 1) {
    $form['names_fieldset']['remove_name'] = array(
      '#type' => 'submit',
      '#value' => t('Remove one'),
      '#submit' => array('ajax_example_add_more_remove_one'),
      '#ajax' => array(
        'callback' => 'ajax_example_add_more_callback',
        'wrapper' => 'names-fieldset-wrapper',
      ),
    );
  }
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Submit'),
  );
  if ($no_js_use) {
    // Remove the #ajax from the above, so ajax.js won't be loaded.
    if (!empty($form['names_fieldset']['remove_name']['#ajax'])) {
      unset($form['names_fieldset']['remove_name']['#ajax']);
    }
    unset($form['names_fieldset']['add_name']['#ajax']);
  }

  return $form;
}

/**
 * Callback for both ajax-enabled buttons.
 *
 * Selects and returns the fieldset with the names in it.
 */
function ajax_example_add_more_callback($form, $form_state) {
  return $form['names_fieldset'];
}

/**
 * Submit handler for the "add-one-more" button.
 *
 * Increments the max counter and causes a rebuild.
 */
function ajax_example_add_more_add_one($form, &$form_state) {
  $form_state['num_names']++;
  $form_state['rebuild'] = TRUE;
}

/**
 * Submit handler for the "remove one" button.
 *
 * Decrements the max counter and causes a form rebuild.
 */
function ajax_example_add_more_remove_one($form, &$form_state) {
  if ($form_state['num_names'] > 1) {
    $form_state['num_names']--;
  }
  $form_state['rebuild'] = TRUE;
}

The above code is taken from the example module with little modification. In this code i have added one more text field called surname with name textfield.

Now when i access form it gives me the form fields as shown in the image given below. Before clicking on Add more button: Before clicking the add more button. A plain form

Now when i click on the Add more button two fields are added as shown in the below image.

After clicking on one Add more button

Here you can notice that there are two continuous Name and then two continuous Surname fields.

But actually i want to show these fields like in group. So the first group of name and surname and then second group of name and surname field.

Fields should be in group

How can i achieve as per the above snapshot ?

1 Answer 1

5

The answer is - you really shouldn't try. The logic behind your form now shows one person with two Names and two SurNames. What you want, I bet, is two persons with one Name and one SurName each. So just group Name and SurName in fieldset and you're good.

If you insist on not doing it, read further. You use $form['names_fieldset']['name'][$i] and $form['names_fieldset']['surname'][$i]. It means $form['names_fieldset']['name'] is created before $form['names_fieldset']['surname'], so everything you put in it will be together and before surname. Just swap indexes and make them look like this: $form['names_fieldset'][$i]['name'], $form['names_fieldset'][$i]['surname'] and you'll be good. Of course $form['names_fieldset'][$i] can be a fieldset by itself, so we are back to first paragraph.

2
  • Did the same mistake not so long ago, you know ;)
    – Mołot
    Commented Jun 26, 2013 at 12:48
  • Thanks for this. I have also found that Name and Surname will be in sequence because it goes by alphabet. In my case I had Name and Email, which works together as per this answer, but were swapped because of alphabet. Solution: add another index: $form['names_fieldset'][$i][0]['name'] and $form['names_fieldset'][$i][1]['email'] Commented Jul 22, 2015 at 6:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.