Text Area

The text area component provides users with a resizable input field for entering longer text content. It includes features like character counting, validation states, and optional helper text to guide users through data entry tasks.

import {TextAreaModule} from "@qualcomm-ui/angular/text-area"

Examples

Simple

The simple <q-text-area> bundles all subcomponents together into a single component.

Optional hint
<q-text-area
  class="w-72"
  hint="Optional hint"
  label="Label"
  placeholder="Placeholder text"
/>

Composite

Build with the composite API for granular control. This API requires you to provide each subcomponent, but gives you full control over the structure and layout.

0
Optional hint
<div class="w-72" q-text-area-root>
  <label q-text-area-label>Label</label>
  <div q-text-area-counter></div>
  <textarea placeholder="Placeholder text" q-text-area-input></textarea>
  <div q-text-area-hint>Optional hint</div>
  <div q-text-area-error-text>Optional error text</div>
</div>

Counter

Display a character count using counter or by setting a maxLength.

By default, the counter displays:

  • count/max when maxLength is set
  • count when only counter is used

Use the q-text-area-counter directive with a display function to customize the format.

0
0/10
0 of 10 characters
<q-text-area class="w-72" counter label="Counter without maxLength" />
<q-text-area
  class="w-72"
  label="Counter with maxLength"
  [maxLength]="10"
/>
<q-text-area class="w-72" label="Custom counter display" [maxLength]="10">
  <div q-text-area-counter [display]="customDisplay"></div>
</q-text-area>

Sizes

Customize size using size. The default size is md.

<q-text-area class="w-56" defaultValue="sm" size="sm" />
<q-text-area class="w-60" defaultValue="md" />
<q-text-area class="w-64" defaultValue="lg" size="lg" />

Value Changed

Listen to changes with the valueChanged output.

import {Component} from "@angular/core"

import {TextAreaModule} from "@qualcomm-ui/angular/text-area"

@Component({
  imports: [TextAreaModule],
  selector: "text-area-value-changed-demo",
  template: `
    <q-text-area
      class="w-72"
      defaultValue="Initial value"
      label="Label"
      placeholder="Placeholder text"
      (valueChanged)="onValueChanged($event)"
    />
  `,
})
export class TextAreaValueChangedDemo {
  onValueChanged(newValue: string) {
    console.log("Value changed:", newValue)
  }
}

Error Text and Indicator

Error messages are displayed using two inputs:

  • invalid
  • errorText (or the q-text-area-error-text directive when using the composite API)

The error text and indicator will only render when invalid is true.

You must enter at least 10 characters.
<q-text-area
  #textArea
  class="w-72"
  errorText="You must enter at least 10 characters."
  label="Label"
  placeholder="Enter at least 10 characters"
  required
  [invalid]="value().length < 10"
  [(ngModel)]="value"
/>

Forms

Control and validate the input value using Angular form control bindings.

Template Forms

When using template-driven forms with ngModel, perform validation manually in your component and pass the result to invalid.

10 characters minimum
import {Component, signal} from "@angular/core"
import {FormsModule} from "@angular/forms"

import {TextAreaModule} from "@qualcomm-ui/angular/text-area"

@Component({
  imports: [TextAreaModule, FormsModule],
  selector: "text-area-template-forms-demo",
  template: `
    <q-text-area
      #textArea
      class="w-72"
      errorText="You must enter at least 10 characters."
      hint="10 characters minimum"
      label="Feedback"
      placeholder="Enter your feedback"
      required
      [invalid]="value().length < 10"
      [(ngModel)]="value"
    />
  `,
})
export class TextAreaTemplateFormsDemo {
  readonly value = signal<string>("Make me shorter")
}

States

When using template forms, disabled, readOnly, and invalid govern the interactive state of the control.

Invalid
<q-text-area disabled label="Disabled" placeholder="Disabled" />
<q-text-area label="Read only" placeholder="Read only" readOnly />
<q-text-area
  errorText="Invalid"
  invalid
  label="Invalid"
  placeholder="Invalid"
/>

Required

When using template forms, pass required to apply the RequiredValidator to the form control.

<q-text-area
  class="w-72"
  label="Required"
  placeholder="Enter text"
  required
  [(ngModel)]="value"
/>

Reactive Forms

Use Reactive Forms for better control of form state and validation.

Minimum 10 characters
import {Component, inject, signal} from "@angular/core"
import {FormBuilder, ReactiveFormsModule, Validators} from "@angular/forms"

import {ButtonModule} from "@qualcomm-ui/angular/button"
import {TextAreaModule} from "@qualcomm-ui/angular/text-area"

@Component({
  imports: [TextAreaModule, ButtonModule, ReactiveFormsModule],
  selector: "text-area-reactive-forms-demo",
  template: `
    <form
      class="mx-auto flex w-72 flex-col gap-3"
      [formGroup]="feedbackForm"
      (ngSubmit)="onSubmit()"
    >
      <q-text-area
        class="w-full"
        errorText="Feedback must be at least 10 characters long"
        formControlName="feedback"
        hint="Minimum 10 characters"
        label="Feedback"
        placeholder="Tell us about your experience"
        [invalid]="isFieldInvalid('feedback')"
      />

      <div class="flex w-full justify-end">
        <button
          emphasis="primary"
          q-button
          type="submit"
          variant="fill"
          [disabled]="isSubmitting()"
        >
          Submit Feedback
        </button>
      </div>
    </form>
  `,
})
export class TextAreaReactiveFormsDemo {
  private fb = inject(FormBuilder)

  readonly isSubmitting = signal(false)

  feedbackForm = this.fb.group({
    feedback: ["", [Validators.required, Validators.minLength(10)]],
  })

  isFieldInvalid(fieldName: string): boolean {
    const field = this.feedbackForm.get(fieldName)
    return !!(field && field.invalid && (field.dirty || field.touched))
  }

  onSubmit() {
    if (this.feedbackForm.valid) {
      this.isSubmitting.set(true)
      console.log("Form submitted:", this.feedbackForm.value)
      // Simulate API call
      setTimeout(() => {
        this.isSubmitting.set(false)
      }, 1000)
    } else {
      // Mark all fields as touched to show validation errors
      this.feedbackForm.markAllAsTouched()
    }
  }
}

State Guidelines

The disabled, invalid, and required inputs have no effect when using Reactive Forms. Use the equivalent Reactive Form bindings instead:

disabledField = new FormControl("")
invalidField = new FormControl("Too short", {
  validators: [Validators.required, Validators.minLength(10)],
})
requiredField = new FormControl("", {validators: [Validators.required]})

ngOnInit() {
  this.disabledField.disable()
  this.invalidField.markAsDirty()
}

Composite API & Forms

When using the composite API with Angular Forms, always apply form control bindings to the q-text-area-root directive.

38
<div
  class="w-72"
  q-text-area-root
  [invalid]="isInvalid()"
  [(ngModel)]="value"
>
  <label q-text-area-label>Composite Forms</label>
  <div q-text-area-counter></div>
  <textarea placeholder="Enter text" q-text-area-input></textarea>
  <div q-text-area-error-text>Must be at least 30 characters long</div>
</div>

API

<q-text-area>

The <q-text-area> component extends the q-text-area-root directive with the following properties:

Groups all parts of the text-area.
PropType
Controls whether to display the counter element.

-
true: always show the counter
-
false: never show the counter
-
undefined (default): only show the counter if maxLength is set
boolean
Optional error that describes the element when invalid is true.
string
Optional hint describing the element. This element is automatically associated with the component's input element for accessibility.
string
Optional label describing the element. Recommended. This element is automatically associated with the component's input element for accessibility.
string
HTML placeholder attribute, passed to the internal input element.
string
Type
boolean
Description
Controls whether to display the counter element.

-
true: always show the counter
-
false: never show the counter
-
undefined (default): only show the counter if maxLength is set
Type
string
Description
Optional error that describes the element when invalid is true.
Type
string
Description
Optional hint describing the element. This element is automatically associated with the component's input element for accessibility.
Type
string
Description
Optional label describing the element. Recommended. This element is automatically associated with the component's input element for accessibility.
Type
string
Description
HTML placeholder attribute, passed to the internal input element.

Composite API

q-text-area-root

Groups all parts of the text-area.
PropTypeDefault
The initial state of the input when rendered. Use when you don't need to control the checked state of the input. This property will be ignored if you opt into controlled state via form control bindings.
string
The document's text/writing direction.
'ltr' | 'rtl'
"ltr"
Controls whether the input is disabled in template-driven forms. When true, prevents user interaction and applies visual styling to indicate the disabled state.
boolean
A root node to correctly resolve the Document in custom environments. i.e., Iframes, Electron.
() =>
| Node
| ShadowRoot
| Document
Controls the visual error state of the input. When true, applies semantic error styling to indicate validation failure.
boolean
The maximum number of characters allowed in the textarea.
number
The name of the input field. Useful for form submission.
string
Whether the input is read-only. When true, prevents user interaction while keeping the input focusable and visible.
boolean
Controls whether the input is required in template-driven forms. When true, the input must have a value for form validation to pass.
boolean
The size of the textarea and its elements. Governs properties like font size, and item padding.
| 'sm'
| 'md'
| 'lg'
'md'
Event emitted when the input value changes. This is only emitted on interaction. It doesn't emit in response to programmatic form control changes.
string
Type
string
Description
The initial state of the input when rendered. Use when you don't need to control the checked state of the input. This property will be ignored if you opt into controlled state via form control bindings.
Type
'ltr' | 'rtl'
Description
The document's text/writing direction.
Type
boolean
Description
Controls whether the input is disabled in template-driven forms. When true, prevents user interaction and applies visual styling to indicate the disabled state.
Type
() =>
| Node
| ShadowRoot
| Document
Description
A root node to correctly resolve the Document in custom environments. i.e., Iframes, Electron.
Type
boolean
Description
Controls the visual error state of the input. When true, applies semantic error styling to indicate validation failure.
Type
number
Description
The maximum number of characters allowed in the textarea.
Type
string
Description
The name of the input field. Useful for form submission.
Type
boolean
Description
Whether the input is read-only. When true, prevents user interaction while keeping the input focusable and visible.
Type
boolean
Description
Controls whether the input is required in template-driven forms. When true, the input must have a value for form validation to pass.
Type
| 'sm'
| 'md'
| 'lg'
Description
The size of the textarea and its elements. Governs properties like font size, and item padding.
Type
string
Description
Event emitted when the input value changes. This is only emitted on interaction. It doesn't emit in response to programmatic form control changes.

q-text-area-label

An accessible label that is automatically associated with the input.
PropType
string
Type
string

q-text-area-hint

Helper text displayed below the textarea.
PropType
string
Type
string

q-text-area-counter

Character counter displayed opposite the textarea label. Renders a <div> element by default.
PropType
Customize how the counter is displayed. Receives the current character count and optional max length, and returns a string.
(
count: number,
maxLength?: number,
) => string
string
Type
(
count: number,
maxLength?: number,
) => string
Description
Customize how the counter is displayed. Receives the current character count and optional max length, and returns a string.
Type
string

q-text-area-input

The text area element. Note: do not apply form control bindings like ngModel or formControl to this element. Apply them to the root element instead.
PropType
string
Type
string

q-text-area-error-text

Error message displayed when the textarea is invalid.
PropType
string
Type
string