I've started using the forms API and am getting into AJAX. There are two places where I've inserted it. The first is a select box which, when changed, updates another part of the form. This part works correctly. The second is a button that adds additional fields to the form when pressed. This doesn't work. I think the problem is that for whatever reason, the form isn't being rebuilt. I've confirmed that my custom submit handler is understanding the button press and is incrementing $form_state['app']['counts'][$fieldname] properly, and my AJAX callback is returning the correct part of the form.

This is the code that generates the form element:

    // If the options include MULTIPLE, add extra fields based on
    // $form_state['app']['counts'][$fieldname] and add a field to
    // increase that number.
    if ($multiple) {
      $form[$fieldname] += array(
        '#type' => 'fieldset',
        '#prefix' => "
", '#suffix' => '
', '#tree' => TRUE, ); // If the field count hasn't been set, set it to 1. if (!isset($form_state['app']['counts'][$fieldname])) { // If there are $values specified, pull the number from there instead. $form_state['app']['counts'][$fieldname] = (empty($values[$fieldname]) ? 1 : count($values[$fieldname])); } // This message appears during the other AJAX callback based on a element, but not when pressing the button. drupal_set_message("$fieldname has {$form_state['app']['counts'][$fieldname]} fields."); for ($i = 1; $i < $form_state['app']['counts'][$fieldname]; ++$i) { $form[$fieldname][$i] = $form[$fieldname][0]; } // Insert the button to add more fields to this part of the form. $form[$fieldname]['more'] = array( '#type' => 'submit', // Should this be 'submit' or 'button'? It doesn't seem to work right with 'button'. '#value' => t('Add another acceptable response'), '#submit' => array('_appform_more'), // I've confirmed that this handler properly increments $form_state['app']['counts'][$fieldname] when the button is pressed. '#limit_validation_errors' => array(), '#ajax' => array( 'callback' => '_appform_ajax', // I've confirmed that this callback is properly returning the correct form element and that $form_state['app']['counts'][$fieldname] has been incremented. Do I need to manually rebuild the form here? 'wrapper' => "appform-$fieldname-div", 'method' => 'replace', 'effect' => 'fade', ), } }

(it's not actually called 'app'; I've changed the name for this request)

Comments

meustrus’s picture

Version: 8.x-dev » 7.14
Issue tags: -JavaScript

So I've made this functional now. I threw in a call to drupal_rebuild_form, and several problems later ended up changing the 'more' button to '#type' => 'button', '#submit' => array() and moved the submit handler code to the AJAX handler (because it won't fire when it is '#type' => 'submit'). Is it OK that the AJAX handler alters form state and rebuilds the form? This is the new AJAX handler:

function _appform_ajax(&$form, &$form_state) {
  // There's some code here to create $fieldname by searching all the possible values for which has a value in $form_state for the 'more' button.
  $fieldname = [...];
  // Increment the counter for this field:
  $form_state['app']['counts'][$fieldname]++;
  // Rebuild the form:
  $form = drupal_rebuild_form($form['#form_id'], $form_state, $form);
  // Now get the correct form element and return it:
  return $form[$fieldname];
}
nod_’s picture

Version: 7.14 » 8.x-dev
Issue tags: +JavaScript

To make ajax form loaded via ajax work Drupal.settings needs to be updated with the ajax settings of the new form elements. I haven't looked at which level that should be done but overall that's the way to go.

meustrus’s picture

I will restate that it does work now; maybe Drupal.settings is getting updated, or maybe there's some kind of black magic going on in my situation to make it work. Unless it needs to be updated for the form to be rebuilt properly? I would like a clarification that it's OK to call drupal_rebuild_form($form['#form_id'], $form_state, $form) inside the AJAX callback.

sokrplare’s picture

Version: 7.14 » 8.x-dev
Issue tags: +JavaScript

Confirming what meustrus ran into. Maybe intended behavior, but seems odd that a callback on a textfield rebuilds the form, but the callback on the submit button doesn't. Dropped in the call to drupal_rebuild_form() and it started working which makes sense.

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.