Skip to content

Checkbox

Viames Marino edited this page Mar 26, 2026 · 3 revisions

Pair framework: Checkbox

Pair\Html\FormControls\Checkbox renders a boolean checkbox input. It looks simple, but its Pair implementation has a few details that are important to document clearly.

Rendered HTML:

<input type="checkbox" value="1" ... />

Main methods

Checkbox defines two concrete methods:

  • render(): string
  • validate(): bool

The shared methods inherited from FormControl are still useful:

  • label()
  • description()
  • value()
  • id()
  • class()
  • data()
  • aria()
  • required()
  • disabled()
  • readonly()

Rendering behavior

render() always outputs:

  • <input ... type="checkbox" value="1">
  • checked="checked" when the current value is truthy
  • the common attributes generated by processProperties()

Basic example:

$enabled = (new \Pair\Html\FormControls\Checkbox('enabled'))
    ->label('Enabled')
    // Any truthy value makes the checkbox checked.
    ->value(true)
    ->class('form-check-input');

echo $enabled->renderLabel();
echo $enabled->render();

Another example with explicit metadata:

$newsletter = (new \Pair\Html\FormControls\Checkbox('newsletter'))
    // Give the checkbox a stable id when the surrounding layout is custom.
    ->id('newsletter-optin')
    ->label('Subscribe to newsletter')
    ->description('We send only product updates and release notes.')
    ->value((bool) $user->newsletter)
    ->class(['form-check-input', 'js-newsletter-toggle']);

Most important implementation detail: validation

Checkbox::validate() always returns true.

This means:

  • Pair does not reject an unchecked checkbox at this control level
  • required() does not create real server-side enforcement for Checkbox
  • you must interpret the checkbox explicitly in your model/controller/request logic if it is business-critical

Example:

$terms = (new \Pair\Html\FormControls\Checkbox('terms'))
    ->label('I accept the terms')
    ->required();

// Current implementation: this is always true.
$isValid = $terms->validate();

required() on checkboxes

This deserves special attention:

  • FormControl::processProperties() does not print the HTML required attribute for Checkbox
  • Checkbox::validate() always returns true
  • renderLabel() can still show the required marker in the label if required() was set

So, in the current implementation, required() is mostly a visual/documentation hint for checkboxes, not a complete enforcement mechanism.

Practical examples

1. Simple enabled/disabled flag

$enabled = (new \Pair\Html\FormControls\Checkbox('enabled'))
    ->label('Enabled')
    // Use the current record value to keep edit forms consistent.
    ->value($record->enabled)
    ->class('form-check-input');

2. Feature flag with frontend hook

$betaAccess = (new \Pair\Html\FormControls\Checkbox('betaAccess'))
    ->label('Enable beta access')
    // The checkbox state often controls another part of the UI.
    ->value($user->betaAccess)
    // data-* attributes are useful for conditional UI logic.
    ->data('target', '#beta-access-options');

3. Terms checkbox with explicit server-side handling

$terms = (new \Pair\Html\FormControls\Checkbox('terms'))
    ->label('I accept the terms')
    ->class('form-check-input');

// Do not rely on Checkbox::validate() for this case.
$accepted = (bool) \Pair\Helpers\Post::get('terms');

4. Read-only checkbox in a review screen

$verified = (new \Pair\Html\FormControls\Checkbox('verified'))
    ->label('Verified')
    ->value($document->verified)
    // readonly is rendered as a shared attribute, although checkbox UX is still browser-dependent.
    ->readonly()
    ->disabled();

Secondary methods worth knowing

  • renderLabel() Useful because checkbox layouts often print label and control in a custom wrapper.
  • description() Adds the standard tooltip icon next to the label.
  • aria() and data() Helpful when the checkbox is part of richer frontend interactions.

Notes

  • Browsers do not submit unchecked checkboxes, so missing keys must be interpreted explicitly on the server side.
  • The rendered checkbox value is always "1".
  • If you need stronger semantics or richer UI, Toggle is often the next control to inspect.

See also: FormControl, Toggle, Select, Post.

Clone this wiki locally