0

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!

4
  • #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
    Oct 10, 2021 at 19:49
  • 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.
    – apaderno
    Oct 10, 2021 at 19:51
  • 1
    @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. Oct 10, 2021 at 20:04
  • 1
    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. */ }
    – apaderno
    Oct 11, 2021 at 7:47

1 Answer 1

1

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

1
  • Wow - thank you very much! This was exactly what I was looking for and it works like desired. Once again, thank you very much! Oct 12, 2021 at 17:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.