How to implement "Add another item" for custom forms?

I am writing a module which is basically a form that creates a relation between two end points.

I want a user to be able to create multiple relations at once. I want to add a button which says "add another item" just like how fields have when you select unlimited in their settings.

Is there a way I can do this to custom forms too ?

Answers 2

  • One way to do this is by setting the form fields/field sets within a for function. Create a seperate function to increment the value via a submit button callback for instance and rebuild the form after you increment.

    for($x=1; $x<=$variabletoincrement; $x++){
    (insert form fields/field sets )
    }
    

    Here is code from form_example_tutorial_9 which shows information on how to create dynamic fields. This information is much more thorough than my explanation:

    http://api.drupal.org/api/examples/form_example!form_example_tutorial.inc/function/form_example_tutorial_9_add_name/7

    http://api.drupal.org/api/examples/form_example%21form_example_tutorial.inc/function/form_example_tutorial_9/7


  • To have a simple and working code example:

    function MYMODULE_MYFORM($form, &$form_state) {
    
      // #tree will ensure the HTML elements get named distinctively.
      // Not just name=[name] but name=[container][123][name].
      $form['#tree'] = TRUE;
    
      if (empty($form_state['number_names'])) {
        $form_state['number_names'] = 1;
      }
    
      for ($i = 1; $i <= $form_state['number_names']; $i++) {
    
        $form['container'][$i] = array(
          '#type' => 'container',
        );
        $form['container'][$i]['name'] = array(
          '#type' => 'textfield',
          '#attributes' =>array('placeholder' => t('Name')),
          '#size' => 20,
          '#required' => TRUE,
        );
      }
    
      $form['add_item'] = array(
        '#type' => 'submit',
        '#value' => t('Add another name'),
        '#submit' => array('MYMODULE_MYFORM_add_item'),
      );
    
      if ($form_state['number_names'] > 1) {
    
        $form['remove_item'] = array(
          '#type' => 'submit',
          '#value' => t('Remove latest name'),
          '#submit' => array('MYMODULE_MYFORM_remove_item'),
          // Since we are removing a name, don't validate until later.
          '#limit_validation_errors' => array(),
        );
      }
    
      // $form['submit'] = array(
      //   '#type' => 'submit',
      //   '#value' => 'Submit',
      // );
    
      return $form;
    }
    
    function MYMODULE_MYFORM_add_item($form, &$form_state) {
    
      // All we need is to increase the number used in our for loop above ...
      $form_state['number_names']++;
      // ... and rebuild our form.
      $form_state['rebuild'] = TRUE;
    }
    
    function MYMODULE_MYFORM_remove_item($form, &$form_state) {
    
      // Just the other way around until only one item is left ...
      if ($form_state['number_names'] > 1) {
        $form_state['number_names']--;
      }
      // ... and form rebuild again.
      $form_state['rebuild'] = TRUE;
    }
    

    Drupal 8

    Check out Example module's AjaxAddMore.php (click the small "View source" link).


Related Questions