1

I have a form where many things happen per ajax request as e.g. a lookup of field values which will be pre-filled on button click

Most of the things work fine but there is one problem when submitting/validating the form. The values which were pre-filled in Step-1 supersede input which was made later in the form.

Here is the code for one of my ajax callbacks and the submit and validation functions:

function _presence_callback($form, &$form_state) {
  if (isset($_POST['ajax_html_ids'])) {
    unset($_POST['ajax_html_ids']);
  }
  //list($form, $form_state) = ajax_get_form();
  drupal_process_form($form['#form_id'], $form, $form_state);

  $commands = array();
  // show invitees section on certain choices in presence field
  $presence = $form_state['input']['field_attendee']['und'][0]['field_presence']['und'];
  $commands[] = ajax_command_replace("#field_evening_div", render($form['field_attendee']['und'][0]['field_evening']));
  if ($presence !== false) {
    if ($presence === "0") {
      $commands[] = ajax_command_css("#invitees_intro_1", array('display' => 'block'));
    } ...
  }
  $page = array('#type' => 'ajax', '#commands' => $commands);
  return $page;
}

/*
 * Code shall be different from default value
 */
function _validate_registration($form, $form_state) {
  $code = $form_state['input']['field_code']['und'][0]['value'];
  $invitations = views_get_view_result('invitations', 'page', $code);
  if (!$invitations) {
    form_set_error('field_code', t('No valid code'));
    return false;
  }
  $registrations = views_get_view_result('invitations', 'page_1', $code);
  if ($registrations) {
    form_set_error('field_code', t('Code already in use'));
    return false;
  } 
  return true;
}

function registration_node_form_submit($form, &$form_state) {
  foreach ($form_state['values']['field_invitee']['und'] as $key=>$el) {
    if (is_numeric($key)) {
        // copy values from one person to some others
    }
  }
}

and here is the form alter function

function vjoonity_code_form_alter(&$form, &$form_state, $form_id) {
  $form['#validate'][] = '_validate_registration';

  // empty default values without code submission
  $first_name = ... = '';


  $values_exist = array_key_exists('values', $form_state);
  if ($values_exist) {
    // take actions on values from ajax lookups
  }
  // values from ajax lookup for pre-filling the attendee form
  if ($values_exist &&  $code_exists) {         
    $salutation = $invitation->field_field_salutation[0]['raw']['value'];
    $title = $invitation->field_field_title[0]['raw']['safe_value'];
    ...
    ...
  }

  // button triggering ajax lookup
  $form['lookup'] = array(
    '#type' => 'button',
    '#value' => t('Go!'),
    '#weight' => 5,
    '#executes_submit_callback' => false,
    '#element_validate' => array('_validate_registration'),
    "#limit_validation_errors" => array(),
    '#ajax' => array(
      'callback' => '_check_callback',
      'wrapper' => array(
        'field_salutation_div',
        'field_title_div',
        ...
        ...
        'code_div',
      ),
      'method' => 'replace',
      'effect' => 'fade',
    )
  );

  // wrappers for ajax around the attendee fields
  if (true) {
    $form['field_attendee']['und'][0]['field_salutation']['#prefix'] = '<div id="field_salutation_div">';
    $form['field_attendee']['und'][0]['field_salutation']['#suffix'] = '</div>';
    ...
  }
  // filling in values from ajax lookup
  if (true) {
    if ($salutation) $form['field_attendee']['und'][0]['field_salutation']['und']['#value'] = array($salutation);
    if ($title) $form['field_attendee']['und'][0]['field_title']['und'][0]['value']['#value'] = $title;
    ...
  }

  // ajax for the presence radio group
  $form['field_attendee']['und'][0]['field_presence']['und']['#ajax'] = array (
    'event' => 'click',
    'callback' => '_presence_callback',
    '#executes_submit_callback' => false,
    //'#element_validate' => array('_validate_registration'),
    'wrapper' => array(
        'further_div',
        'field_evening_div',
        'show_invitees_div',
    ),
    'method' => 'replace',
    'effect' => 'fade',
  );

  ....
}

My problem is that in form validation and form submission of the whole form the values array still shows values from the ajax callback and take these as actual form values instead of taking changes to the formular into account.

1

I solved it. One problem was using ajax callbacks instead of ajax paths. Though different Callbacks they all redirected to one callback function. With paths it's not a problem.

Secondly the code had a problem with image buttons as ajax-enabled elements. The final submit always thought to be triggered by one of the ajax buttons though it was the submit button just ordinarily.

Thirdly injecting an indicator value in the callback function to the form_state and then use it in the form function for further decision taking is certainly the more correct way to do it than mis-using the button values in form_states' values array. These neither aren't very consistent nor persistent.

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.