A single checkbox is the simplest form element there is — one box, checked or not. Simple as it looks, its submitted value works a little differently from every other element type, and that difference is worth understanding before it surprises you in a validation function.
What you'll learn in this lesson
- The basic checkbox definition
- Exactly what value gets submitted when checked versus unchecked
- Setting a checked-by-default state with
#default_value
A basic checkbox
$form['agree_terms'] = [
'#type' => 'checkbox',
'#title' => $this->t('I agree to the terms and conditions'),
'#required' => TRUE,
];
Notice the title here reads as a full statement rather than a short label — that's the convention for a single checkbox specifically, since the checkbox and its title together form one sentence a user reads and agrees (or doesn't agree) to.
What actually gets submitted
This is the detail that catches people off guard: a checkbox's submitted value is always either 1 (checked) or 0 (unchecked) — never a boolean TRUE/FALSE, and critically, never absent. Unlike a raw HTML checkbox (where an unchecked box simply isn't included in the submitted form data at all), Drupal's Form API guarantees the key always exists in $form_state->getValues(), set to 0 when unchecked. This is deliberate — it means $form_state->getValue('agree_terms') is always safe to read directly, with no need for an isset() check first.
if ($form_state->getValue('agree_terms')) {
// Checked — value is 1 here, not TRUE.
}
Setting the default checked state
'#default_value' => $config->get('feature_enabled') ? 1 : 0,
Use 1/0 (or any truthy/falsy PHP value) here — Drupal coerces it correctly either way, but writing it explicitly as 1/0 keeps it consistent with what actually comes back from the submitted form.
$form_state->getValue('agree_terms') == FALSE technically works because PHP coerces 0 == FALSE to true, but relying on loose comparison habits with form values is a good way to introduce a subtle bug later when you're less careful. Prefer a direct truthy check (if (!$form_state->getValue('agree_terms'))) or an explicit === 0 when you genuinely need strictness.Quick check: a user submits a form leaving an optional checkbox unchecked. Is the key present at all in
$form_state->getValues()? (Yes — set to0. This is different from a raw HTML form, where an unchecked checkbox is simply omitted from the POST data entirely. Drupal's Form API always includes the key.)
Key takeaways
- A checkbox's submitted value is always
1or0— never absent, unlike a raw HTML checkbox. - Because the key is always present, you never need an
isset()guard before reading a checkbox's value. - Phrase a single checkbox's
#titleas a complete statement — box and label together read as one sentence.
Coming up next
One checkbox handles a single yes/no. The next lesson covers checkboxes (plural) — letting a user select any number of options from a list.