0

I am using ajax to show/hide a field based on a date field. I set the default access to TRUE. If the user selects a date of birth over 18 years old, $is_younger and consequently the access switch to FALSE.

function mrpeanut_form_record_node_form_alter(&$form, &$form_state, $form_id) {
    // some other stuff here
    $is_younger = TRUE;
    $values = !empty($form_state['values']) ? $form_state['values'] : array();
    $dob_date_combo_element = &$form['field_dob']['und'][0];
    $dob_date_combo_element['#ajax'] = [
      'callback' => 'mrpeanut_form_record_node_form_minor_agreement_callback',
      'wrapper' => 'minor-ajax',
      'effect' => 'fade',
    ];

    if (!empty($values['field_dob']['und'][0]['value'])) {
      $dob = new DateTime($values['field_dob']['und'][0]['value']);
      $now = new DateTime();
      $age = $now->diff($dob)->y;
      $is_younger = $age < 18;
    }

    $form['field_minor_agreement']['und']['#access'] = $is_younger;

This is working great until the user selects and uploads an image on a separate image field. Then, $is_younger switches back to TRUE, regardless of whether they are over 18 or not. I can't seem to figure out why.

I think the error is happening on this line:

if (!empty($values['field_dob']['und'][0]['value']))

After I upload an image, I get this error if I try to watchdog the value.

Notice: Undefined index: field_dob in mrpeanut_form_record_node_form_alter()

I think $values is getting overwritten after the image is uploaded and therefore date of birth can't be calculated again and it reverts back to $is_younger = TRUE.

Here's my callback:

function mrpeanut_form_record_node_form_minor_agreement_callback($form, $form_state) {
  $commands = array();
  $commands[] = ajax_command_replace('#edit-field-minor-agreement-wrapper', drupal_render($form['field_minor_agreement']));
  return array('#type' => 'ajax', '#commands' => $commands);
}
  • is that drupal 7 or 8 , is that simple of code from form build function or callback function ? – berramou Oct 30 '18 at 20:08
  • Drupal 7 and sorry, that's from hook_form_alter. I'll update. – MrPeanut Oct 30 '18 at 20:09
  • Could you post the code from mrpeanut_form_record_node_form_minor_agreement_callback? It might not be relevant but useful to rule it out nonetheless – Clive Oct 30 '18 at 20:32
  • Okay, added the callback. – MrPeanut Oct 30 '18 at 20:36
  • Would I be better off storing $is_younger in a session variable like so -- $_SESSION['is-younger'] = $is_younger -- so that when $values gets overwritten, the variable is still there? – MrPeanut Oct 30 '18 at 20:58
0

I would try refactoring your code, so that the part that produces the value of $is_younger first checks whether the triggering element is the field_dob field.

As an example:

// some other stuff here
$dob_date_combo_element = &$form['field_dob']['und'][0];
$dob_date_combo_element['#ajax'] = [
  'callback' => 'mrpeanut_form_record_node_form_minor_agreement_callback',
  'wrapper' => 'minor-ajax',
  'effect' => 'fade',
];

// Were we called by the #ajax-ified element?
if (isset($form_state['triggering_element']) && 
  $form_state['triggering_element']['#name'] === 'field_dob[und][0][value]') {
  $values = !empty($form_state['values']) ? $form_state['values'] : array();
  $is_younger = TRUE;

  if (!empty($values['field_dob']['und'][0]['value'])) {
      $dob = new DateTime($values['field_dob']['und'][0]['value']);
      $now = new DateTime();
      $age = $now->diff($dob)->y;
      $is_younger = $age < 18;
  }
  $form['field_minor_agreement']['und']['#access'] = $is_younger;
}
// Initial form loading.
else if (empty($form_state['input']) {
  // Place initial loading logic here for field_minor_agreement.
}

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.