Drupal Answers is a question and answer site for Drupal developers and administrators. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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();
}
share|improve this question
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

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,
    );
share|improve this answer

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();
    }
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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