6

I am trying to add a combination of text field and a select box to a form dynamically using Drupal 7 Ajax, when i click on a button.

But i have 2 issues here:

  1. I am not able to add more than 1 set of fields in the form with Ajax
  2. After i submit the form, i am not able to retrieve the values of the form. They are empty. I have the fields as "name_1", "select_1", "name_2", "select_2", etc.

I want to know if there is any way to solve it, with / without using a fieldset.

My custom module code:

function my_form_form($form, &$form_state, $no_js_use = FALSE) {  
  $form['#tree'] = TRUE;
  $form['add_more'] = array(
    '#type' => 'button',
    '#value' => t('Add More'),
    '#href' => '',
    '#ajax' => array(
    'callback' => 'ajax_simplest_callback',
    'wrapper' => 'names-fieldset-wrapper',
  );
  $form['names']['name_1'] = array(
    '#type' => 'textfield', 
    '#title' => t('Name 1'),  
    '#attributes'=>array('id'=>'name_1', 'name'=>'name_1'),           
  );
  $form['names']['select_1'] = array(
    '#type' => 'select', 
    '#title' => t('Select 1'),    
    '#attributes'=>array('id'=>'select_1', 'name'=>'select_1'), 
    '#options'=>array('1'=>'One', '2'=>'Two', '3'=>'Three'),
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Submit'),  
  );
  $form['#submit'][] = 'my_form_add_more_submit';       
  return $form;
}
function ajax_simplest_callback($form, &$form_state) {
  if (empty($form_state['num_names'])) {
    $form_state['num_names'] = 1;
  }
  else {
    $form_state['num_names']++;
    $form_state['rebuild'] = TRUE;
  }

  for ($i = 1; $i < $form_state['num_names']; $i++) {       
    $form['names']['name_'.$i+1] = array(
      '#type' => 'textfield', 
      '#title' => t('Name '.$i+1),    
      '#attributes'=>array('id'=>'name_'.$i+1, 'name'=>'name_'.$i+1), 
    );    
    $form['names']['select_'.$i+1] = array(
      '#type' => 'select', 
      '#title' => t('Select '.$i+1),    
      '#attributes'=>array('id'=>'select_'.$i+1, 'name'=>'select_'.$i+1), 
      '#options'=>array('1'=>'One', '2'=>'Two', '3'=>'Three'),
    );
  }
  return $form['names'];
}

function my_form_add_more_submit($form, &$form_state) {
  print_r($form_state['values']);
  exit();
}
4
  • 1
    You must add the wrapper div with id names-fieldset-wrapper Apr 17, 2013 at 16:15
  • At which place in the code, do i need to add that div (as a prefix or suffix)? Apr 18, 2013 at 5:27
  • as wrapper of form elements you want to add. Apr 18, 2013 at 15:10
  • Your #ajax property value doesn't have a closing parenthesis for the array.
    – mbomb007
    Apr 22, 2019 at 18:36

2 Answers 2

1

Dont set any field #required to true.

 $form['markup'] = array(
        '#type' => 'markup',
        '#prefix' => '<div id="my-wrapper">',
        '#suffix' => '</div>',
    );
 $form['markup']['myfield'] = array(
        '#type' => 'textfield', 
        '#size' => 12,
    );
1

You need to rebuild your form in your form function so you values get integrated into the form. You also want to make use of fieldsets and their tree structure to make the data a bit more organized.

function my_form_form($form, &$form_state, $no_js_use = FALSE) {

        $form['add_more'] = array(
          '#type' => 'button',
          '#value' => t('Add More'),
          '#ajax' => array(
            'callback' => 'ajax_simplest_callback',
            'wrapper' => 'replace-this',
            'method' => 'replace',
           ),
        );

        $form['names'] = array(
          '#type' => 'fieldset',
          '#title' => 'Names',
          '#prefix' => '<div id="replace-this">',
          '#suffix' => '</div>',
          '#tree' => TRUE,
        );

        // build the initial field if this is not being rebuilt 
        // from ajax request
        if (!array_key_exists('clicked_button', $form_state)) {
          $form['names'][0] = array('#type' => 'fieldset');
          $form['names'][0]['name'] = array(
            '#type' => 'textfield',
            '#title' => t('Name'),
            '#parent' => 'test',
          );
          $form['names'][0]['select'] = array(
            '#type' => 'select',
            '#title' => t('Select'),
            '#parent' => 'test',
            '#options'=>array('1'=>'One', '2'=>'Two', '3'=>'Three'),
          );
        } else {
          // otherwise add the fields for each existing value
          foreach ($form_state['input']['names'] as $i => $value) {
            $form['names'][$i] = array('#type' => 'fieldset');
            $form['names'][$i]['name'] = array(
              '#type' => 'textfield',
              '#title' => t('Name'),
              '#default_value' => $form_state['input']['names'][$i]['name'],
            );
            $form['names'][$i]['select'] = array(
              '#type' => 'select',
              '#title' => t('Select'),
              '#default_value' => $form_state['input']['names'][$i]['select'],
              '#options'=>array('1'=>'One', '2'=>'Two', '3'=>'Three'),
            );
          }

          // add the additional field for a new entry
          $last = count($form_state['input']['names']);
          $form['names'][$last] = array('#type' => 'fieldset');
          $form['names'][$last]['name'] = array(
              '#type' => 'textfield',
              '#title' => t('Name'),
          );
          $form['names'][$last]['select'] = array(
              '#type' => 'select',
              '#title' => t('Select'),
              '#options'=>array('1'=>'One', '2'=>'Two', '3'=>'Three'),
          );
        }

        $form['submit'] = array(
          '#type' => 'submit',
          '#value' => t('Submit'),
        );
        $form['#submit'][] = 'my_form_add_more_submit';

        return $form;
    }

    function ajax_simplest_callback($form, &$form_state) {
        return $form['names'];
    }

    function my_form_add_more_submit($form, &$form_state) {
        print_r($form_state['values']);
        exit();
    }

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.