Skip to content

Textarea

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

Pair framework: Textarea

Pair\Html\FormControls\Textarea renders multi-line text fields. It is one of the most used controls in Pair forms whenever the content is longer than a simple label, title, or code.

Rendered HTML:

<textarea ...>content</textarea>

Main methods

Textarea adds four practical methods:

  • rows(int $rowsNumber): self
  • cols(int $columnsNumber): self
  • value(string|int|float|DateTime|null $value): static
  • render(): string

Inherited methods from FormControl remain important here as well:

  • label()
  • description()
  • required()
  • readonly()
  • disabled()
  • placeholder()
  • class()
  • data()
  • id()
  • validate()

Most important behavior: value(...) writes the inner content

Unlike input-based controls, Textarea does not render a value="..." attribute.

Its value(...) method forwards the content to caption(...), which means the text is placed between the opening and closing <textarea> tags.

$description = (new \Pair\Html\FormControls\Textarea('description'))
    // rows and cols are optional layout hints.
    ->rows(6)
    ->cols(80)
    // Placeholder is supported on textarea.
    ->placeholder('Describe the issue')
    ->required()
    // value() becomes the visible inner content of the textarea.
    ->value('Initial content');

echo $description->render();

This is important when you compare Textarea with Text, Email, or Number: those controls store the value in the HTML value attribute, while Textarea stores it in the element body.

Layout methods: rows(...) and cols(...)

rows(...) and cols(...) are small but useful methods when the visual size matters.

$message = (new \Pair\Html\FormControls\Textarea('message'))
    ->label('Message')
    // Give the user enough vertical space for a real note.
    ->rows(8)
    // cols is optional and mostly useful in simpler layouts.
    ->cols(100);

If you do not call them, Pair simply omits those attributes.

Rendering behavior

render():

  • opens <textarea ...>
  • appends rows and cols when configured
  • reuses processProperties() for shared attributes
  • writes the escaped caption/content inside the tag
  • closes </textarea>

Example with a custom layout:

$internalNote = (new \Pair\Html\FormControls\Textarea('internalNote'))
    // Explicit ids are useful when the layout references the field directly.
    ->id('internal-note')
    ->label('Internal note')
    ->rows(5)
    ->class(['form-control', 'font-monospace'])
    ->value($ticket->internalNote);

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

Validation

Textarea does not override validate(), so it uses the base FormControl::validate() method.

That means:

  • required() is enforced server-side
  • minLength() and maxLength() are enforced server-side if configured
  • validation reads the submitted value from Post::get($this->name)

Example:

$summary = (new \Pair\Html\FormControls\Textarea('summary'))
    // These constraints are checked against the submitted POST payload.
    ->required()
    ->minLength(20)
    ->maxLength(2000);

// The validator checks the submitted POST value for "summary".
$isValid = $summary->validate();

Secondary methods worth knowing

  • caption(...) Textarea is one of the few controls that supports it directly.
  • placeholder(...) Supported here, unlike on controls such as Checkbox.
  • inputmode(...) Inherited but ignored by the current implementation for Textarea.

Practical examples

1. Description field in a CRUD form

$description = (new \Pair\Html\FormControls\Textarea('description'))
    ->label('Description')
    // A medium height works well for CRUD edit forms.
    ->rows(6)
    ->placeholder('Describe the issue or the feature request')
    ->required()
    ->value($task->description ?? '');

2. Read-only audit trail

$notes = (new \Pair\Html\FormControls\Textarea('notes'))
    ->label('Audit trail')
    ->rows(4)
    // readonly is useful when the user can inspect but not edit.
    ->readonly()
    ->value($auditTrailText);

3. Comment box with frontend metadata

$comment = (new \Pair\Html\FormControls\Textarea('comment'))
    ->label('Comment')
    ->rows(5)
    ->class(['form-control', 'js-markdown-input'])
    // data-* attributes can drive preview or autosave behaviors.
    ->data('autosave', '1')
    ->data('preview-target', '#comment-preview');

4. Detached textarea associated with another form

$quickReply = (new \Pair\Html\FormControls\Textarea('quickReply'))
    ->label('Quick reply')
    ->rows(3)
    // Useful in toolbars or side panels rendered outside the main form.
    ->form('conversation-form');

Notes

  • value(...) does not behave like an input value attribute; it becomes the textarea body.
  • inputmode(...) is ignored for Textarea in the current implementation.
  • If you need rich-text or markdown behavior, Textarea is usually the clean starting point and JavaScript can enhance it later through CSS classes or data-* attributes.

See also: FormControl, Text, Form.

Clone this wiki locally