0

Suppose I have a form only with a submit button. After an AJAX response (not an #ajax form callback) I need to insert/append a new form element into this form.(it's not declared in the form-building function)

How will I initialize this new form element in the PHP callback function, in order to populate it with the data i am getting through ajax?

I could have initialize the form with a dummy element and copy its array to a new one?How will I hide this dummy element in the initial state of the form (before ajax)?

In the "Add more" examples out there, the initial form carries the first of these elements from the beginning... what if there is not from the beginning in the form?

In other words how can I get anywhere in the code a fresh-empty form element ready to be rendered?

2 Answers 2

2

You can add some custom value to the form_state and use it to determine whether to build a new form element or not. Please try the following example:

/**
 * An example form.
 */
function example_form($form, &$form_state) {

  $form['#tree'] = TRUE;

  // Use this value to determine whether to build a new form element or not.  
  if (empty($form_state['add_new_item'])) {
    $form_state['add_new_item'] = FALSE;
  }

  $form['example_fieldset'] = array(
    '#type' => 'fieldset',
    '#title' => t('Example form'),
    // Set up the wrapper so that AJAX will be able to replace the fieldset.
    '#prefix' => '<div id="example-fieldset-wrapper">',
    '#suffix' => '</div>',
  );

  $form['example_fieldset']['name'] = array(
    '#type' => 'textfield',
    '#title' => t('Name'),
    '#required' => FALSE,
  );

  $form['actions'] = array(
    '#type' => 'actions'
  );

  // add field button.
  $form['actions']['add_field'] = array(
    '#type' => 'submit',
    '#value' => t('Add new form item'),
    '#submit' => array('field_add_one'),
    '#ajax' => array(
      'callback' => 'example_form_callback',
      'wrapper' => 'example-fieldset-wrapper',
    ),
    // hide this form element
    '#attributes' => array(
      'class' => array('element-invisible')
    )
  );

  // submit button.
  $form['actions']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Submit')
  );

  $form['#attached']['js'] = array(
    array(
      'type'  => 'file',
      'data' => drupal_get_path('module', 'YOUR_MODULE') . '/js/add_field.js',
    ),
  );

  // append a new form element (after ajax)
  if ($form_state['add_new_item'] == TRUE) {
    $form['example_fieldset']['new_item'] = array(
      '#type' => 'textfield',
      '#title' => 'My new item',
    );
  }

  return $form;
}


/**
 * Submit handler for the "add-field" button.
 *
 * - set the $form_state['add_new_item'] as TRUE.
 * - rebuild the form.
 */
function field_add_one($form, &$form_state) {
  $form_state['add_new_item'] = TRUE;
  $form_state['rebuild'] = TRUE;
}

/**
 * Ajax callback.
 *
 * Returns the fieldset with all values in it.
 */
function example_form_callback($form, &$form_state) {

  return $form['example_fieldset'];
}

/**
 * Final submit handler.
 *
 * Reports what values were finally set.
 */
function example_form_submit($form, &$form_state) {
  $output = $form_state['values']['example_fieldset'];
  drupal_set_message('<pre>' . print_r($output, true) . '</pre>');
}

add_field.js

(function($) {    
  Drupal.behaviors.your_module_name = {
    attach:function() {

      var form = $('#example-form');

      // the 'add-field' form element
      // this form element is invisible. It will be triggered by the custom link (not form element).
      var addField = $('#edit-actions-add-field'); 

      // add an example link
      $('#my-custom-link').remove(); // prevent from adding the custom link more than once
      form.after("<span id='my-custom-link'><a href='#'>ADD FIELD</a></span>"); // add custom link

      // Attach mousedown() to the custom link in order to activate ajax.
      // Notice: You can attach click() to a normal submit form element (without ajax)
      // but it has to be mousedown() if the form element has an ajax attribute.
      $('#my-custom-link').click(function() {
        addField.mousedown(); 
      });
    }
  };
}(jQuery));
2
  • Thank you ,u must understand that i don't have accessto $form_state because as i say before the js action is not triggered by a form element...
    – Pan Chrono
    Sep 5, 2013 at 7:46
  • 1
    If you're dealing with the form, there is always an access to form_state. To trigger the form alement by something which is not a form element, it is a different story. You can use javascript for that. I edited my answer and added an example.
    – Jack-PL
    Sep 5, 2013 at 23:03
0

In your callback function you should be able to return a new form element like:

function YOURMODULE_your_callback($form, &$form_state) {
  $form['new_item'] = array(
    '#type' => 'textfield',
    '#title' => 'My new item',
  );
  return $form['new_item'];
}

Doesn't that work?

1
  • This works but only for some of the elements. managed_file does not work.
    – Rick
    Jun 29, 2016 at 3:28

Your Answer

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

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