Score:0

Throw error for required field in hook_form_alter?

cn flag

I have a node type that can be created by authenticated users. In the node create form, I added a terms-of-service checkbox via a form hook like so:

function themename_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'node_nodetype_form') {
    $form['field_tos_accept'] = array(
      '#type' => 'checkbox',
      '#title' => t('I agree to the terms of service.'),
      '#weight' => '999',
      '#required' => TRUE,
    );
  }
}

This gives me the ability to have this checkbox in the node create form, but not in node edit form since it isn't needed there. When I add

'#required_error' => t('Please accept the terms of service.'), 

This should - in my understanding - throw an error message when the form is submitted. But instead the required state of the field prevents the form from beeing submitted. So, there's also no error message thrown.

Is there any way to set this in a form_alter? Or should I just validate the checkbox state via JS? What would be considered best practise? Thank you very much in advance!

apaderno avatar
us flag
`#required_error` is the error shown when the form is validated and the form element is required, but users didn't enter any value. `#required` is used to mean users must enter a value for that form element. Neither of them prevent the form to be submitted. As long as users provide a value for that form element, the form is submitted.
apaderno avatar
us flag
Also, if you are adding the checkbox only when a node is created, but not when a node is edited, you are using more code than the question is showing.
Berry Dingle avatar
cn flag
@apaderno I use just the above code in my themename.theme file. But since I hook into the node-nodetype-form and not into the node-nodetype-edit-form, it's only shown in the node add/create form, and not in the edit form. You are right about the submission. The required state doesn't prevent form submission, but triggers the default HTML5-field validation which I don't see because I made a switch button out of the default checkbox input. Guess I'll do it in JS and throw an error when the submit button is clicked, but the checkbox is not checked.
apaderno avatar
us flag
The form to edit a node is the same form used to create it, the one implemented by the `Drupal\node\NodeForm` class. If you want to add a form element only when the node is created, you should add code similar to the following one: `$node = $form_state->getFormObject()->getEntity(); if ($node && $node->isNew()) { /* The node is being created. */ }`
Score:1
cn flag

Is there any way to set this in a form_alter? Or should I just validate the checkbox state via JS?

You could replace #required by setting a custom validation handler in the form alter hook, if you want to generate the error message server-side:

$form_state->setErrorByName('field_tos_accept', $error_message);

When I add '#required_error', this should - in my understanding - throw an error message when the form is submitted.

#required_error' was introduced in 2011, but when Drupal 8 was released it seems to have stopped working in browsers supporting HTML5 form validation and so it was never really adopted.

However, you can use the HTML5 form attribute novalidate to disable client-side form validation, then this property works again and you get the custom error message without a custom validation handler:

function themename_form_alter(&$form, &$form_state, $form_id) {
  // for entity forms $form_id consists of
  // ENTITY_TYPE_BUNDLE_FORM_MODE_form
  // BUNDLE only if entity has bundles
  // FORM_MODE only if not default
  // Examples:
  // node_article_edit_form - node edit form for the content type article
  // node_page_form - node create form for the content type page
  // nodes use for the create form the form mode default
  if ($form_id == 'node_nodetype_form') {
    $form['#attributes']['novalidate'] = 'novalidate';
    $form['field_tos_accept'] = [
      '#type' => 'checkbox',
      '#title' => t('I agree to the terms of service.'),
      '#weight' => '999',
      '#required' => TRUE,
      '#required_error' => t('Please accept the terms of service.'), 
    ];
  }
}

See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#attr-novalidate

Berry Dingle avatar
cn flag
Wow - thank you very much! This was exactly what I was looking for and it works like desired. Once again, thank you very much!
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.