0

On a node/add form I have a pair of fields that need to be able to control one another. The first field allows a user to enter a birthdate, the second field allows the user to say the birthdate is unknown.

I have attempted to work with Conditional Fields to make this work but I think for my case AJAX would be better.

If the birthdate_unkown field is not checked then the birthdate field should be required. When the birthdate_unkown field is checked then I would like to be able to make it so that the field is no longer required.

I have a working AJAX callback function I just cannot figure out how to use AJAX to change if the field is required or not.

I have tried options like:

$response->addCommand(new InvokeCommand('edit-field-birthdate-0-value-date','attr',['required', false]));

or

$response->addCommand(new InvokeCommand('edit-field-birthdate-0-value-date','removeAttr',['required']));

I have this code in a function that looks like this:

function _custom_field_unknown_birthday_logic(&$form, FormStateInterface $form_state) {
    \Drupal::logger('custom')->error('Unknown Birthday Callback');
    $values = $form_state->getValues();
    $unknown_birthdate = $values['field_unknown_birthdate']['value'];
    \Drupal::logger('custom')->error('Unknown Birthday Callback Value '. $unknown_birthdate);

    $response = new AjaxResponse();
    if ($unknown_birthdate == false) {
        $response->addCommand(new InvokeCommand('edit-field-birthdate-0-value-date','attr',['required']));
        \Drupal::logger('custom')->error('Birthdate IS required');
    } else if ($unknown_birthdate == true) {
        $response->addCommand(new InvokeCommand('edit-field-birthdate-0-value-date','removeAttr',['required'] ));
        \Drupal::logger('custom')->error('Birthdate IS NOT required');
    } else {
        \Drupal::logger('custom')->error('No Change to Birthdate');
    }
    return $response;
}

With the extensive logging I am doing I can see that I am getting to the right places in the code to issue the AJAX commands. That said the AJAX commands do not appear to change anything. I do not see anything in the console for Dev Tools either.

Any help on figuring out how to do this with AJAX is greatly appreciated. Once I get this working with AJAX there is more that needs to be accomplished that will not work with just States API.

Thanks!

4
  • Please show more of your code.
    – cilefen
    Mar 13 at 8:31
  • @cilefen, I have added more code. If you are able to help I would greatly appreciate it. Mar 13 at 17:49
  • Is _custom_field_unknown_birthday_logic() an #ajax callback? And what version of Drupal is this?
    – Jaypan
    Mar 13 at 17:54
  • @Jaypan, yes _custom_field_unknown_birthday_logic() is the callback. I am in Drupal 9. Thanks! Mar 13 at 22:12

1 Answer 1

1

Changes to the form must be made in the form definition, and cannot be made in the ajax callback, as Drupal has already cached the form by the point of the ajax callback, so even if you figured out a way to remove the required attribute on the field in the ajax callback, Drupal would reject a missing value as the form cache from before the ajax callback will still have the form field marked as required.

Instead, in your form definition (not the #ajax callback), you likely want some version of this:

if ($form_state->getValue('field_unknown_birthdate')) {
  unset($form['field_birthday_value']['widget']['#required']);
}

Note that I am guessing the location of the #required key, as well as the field names, so you'll have to inspect the actual $form object to determine the array in which the #required key is set, and unset it.

7
  • Thank you for this response. The reason I was trying to use AJAX is because if I put this in the form alter it will not "know" that the value changed in the Boolean field. Where can I put this so that Drupal will be "aware" of the code . I also tried putting it in a custom submit handler that did not work. thanks! Mar 14 at 17:12
  • Form alter hooks are called on ajax rebuilds, so the value of the field IS known when the alter hook is called as the form is rebuilt. So you put this in your form alter hook.
    – Jaypan
    Mar 14 at 19:25
  • thank you continuing to help. I am sorry if I am missing something obvious here. If I am not changing the required status of the field then I do not necessarily need have an AJAX callback. I am familiar with $form_state->setRebuild() in custom forms. I am not sure how I would do that with in this case? Should I call an AJAX function and just return nothing? Thanks for the clarification. Mar 16 at 2:08
  • I thought the whole point is that you want to change the required status. I'm confused.
    – Jaypan
    Mar 16 at 2:31
  • Jaypan, yes that is the whole point. I am not sure where to put the code you recommended so that when the value of Boolean field changes your recommendation will run. My understanding was that you said that the hook_form_alter I am using would be a good place to put it because the form would be rebuilt. I think for the form to be rebuilt I need an AJAX event. I tried just returning an empty response to test and that did not run the code you suggested. I am looking to better understand where I should put this code so that it will be executed when the field changes. Thank you! Mar 17 at 6:08

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.