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();
}
  • 1
    You must add the wrapper div with id names-fieldset-wrapper – Sumit Madan Apr 17 '13 at 16:15
  • At which place in the code, do i need to add that div (as a prefix or suffix)? – shasi kanth Apr 18 '13 at 5:27
  • as wrapper of form elements you want to add. – Sumit Madan Apr 18 '13 at 15:10
  • Your #ajax property value doesn't have a closing parenthesis for the array. – mbomb007 Apr 22 '19 at 18:36
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, privacy policy and cookie policy

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