Checking #required fields automaticallyfor Drupal 8 , 9 , 10 , and 11

Last updated :  

The most common validation rule on any form isn't a clever regex or a cross-field comparison — it's simply "don't let this be blank." Drupal handles that single most frequent case with one property, no custom validation method required at all: #required.

What you'll learn in this lesson

  • How #required => TRUE triggers automatic, built-in validation
  • Where the "field is required" error message comes from, and how to customize it
  • Why #required checks run before your own custom validators
  • The difference between an empty string and a genuinely absent value for different element types

Marking a field required

$form['email'] = [
  '#type' => 'email',
  '#title' => $this->t('Email address'),
  '#required' => TRUE,
];

Set #required => TRUE on any element and two things happen automatically, with zero code from you: a red asterisk appears next to the label so the visitor knows before they even try to submit, and Drupal's own built-in validation refuses the submission if that field is left empty — generating a generic but perfectly serviceable error message on its own.

Customizing the required-field message

$form['email'] = [
  '#type' => 'email',
  '#title' => $this->t('Email address'),
  '#required' => TRUE,
  '#required_error' => $this->t('We need an email address so we can send your confirmation.'),
];

By default, Drupal's generated message is something like "Email address field is required." — functional, but generic. Set #required_error to override it with wording specific to why the field actually matters, without writing any validation logic yourself.

Required checks run before your own validators

Drupal's own #required check happens automatically as part of core's form processing, before your validateForm() method or any #element_validate callback runs. This matters in practice: if you write a custom validator that reads and processes a field's value, you can generally assume that by the time your code runs, a required field is guaranteed non-empty — you don't need to re-check for blankness yourself on top of #required.

What counts as "empty" varies by element type. For a textfield, empty means an empty string. For a checkbox, "unchecked" is the empty state. For a checkboxes group or a multi-value select, an empty array counts as empty. #required understands all of these per-type correctly — you don't need different logic for different element types.

See it for yourself

Mark a text field #required => TRUE, submit the form with it blank, and confirm Drupal blocks submission and shows an error — without you writing a single line of validation code. Then add #required_error and confirm your custom wording replaces the generic message.

Quick check: you mark a checkbox #required => TRUE. What does "required" actually mean for a checkbox — must it be checked, or just present in the submission? (Answer: it must be checked. An unchecked checkbox is Drupal's definition of "empty" for that element type, so #required forces the visitor to check it, not merely acknowledge it exists.)

Key takeaways

  • #required => TRUE gives you automatic required-field validation with zero custom code — plus a visual asterisk on the label.
  • Override the generated error text with #required_error when the generic message isn't specific enough.
  • #required checks run before your own validateForm()/#element_validate callbacks, so you can generally trust a required field is non-empty by the time your custom code runs.
  • "Empty" is defined per element type: blank string for text fields, unchecked for checkboxes, empty array for multi-value selects/checkboxes groups.

Coming up next

Required-field checks and single-element validators only get you so far. Next, you'll write genuinely custom validation logic in validateForm() itself — the place to reach for when a rule needs to look at more than one field at once.