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.
<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.
<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/maxwhenmaxLengthis setcountwhen onlycounteris used
Use the q-text-area-counter directive with a display function to customize the format.
<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:
The error text and indicator will only render when invalid is true.
<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.
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.
<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.
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.
<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:
| Prop | Type |
|---|---|
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 |
string | |
To customize the element, provide it using the directive instead: <div q-text-area-error-text>...</div> | |
Optional hint describing the element. This element is automatically
associated with the component's input element for accessibility. | string |
To customize the element, provide it using the directive instead: <div q-text-area-hint>...</div> | |
Optional label describing the element. Recommended. This element is
automatically associated with the component's input element for
accessibility. | string |
To customize the element, provide it using the directive instead: <label q-text-area-label>...</label> | |
HTML placeholder attribute,
passed to the internal input element. | string |
boolean-
true: always show the counter-
false: never show the counter-
undefined (default): only show the counter if maxLength is setstring<div q-text-area-error-text>...</div>
string<div q-text-area-hint>...</div>
string<label q-text-area-label>...</label>
stringComposite API
q-text-area-root
| Prop | Type | Default |
|---|---|---|
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. | () => | |
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' |
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 |
string'ltr' | 'rtl'
boolean() =>
| Node
| ShadowRoot
| Document
booleannumberstringbooleanboolean| 'sm'
| 'md'
| 'lg'
string| Attribute / Property | Value |
|---|---|
class | 'qui-text-area__root' |
data-disabled | |
data-focus | |
data-invalid | |
data-part | 'root' |
data-scope | 'text-area' |
data-size | | 'sm' |
class'qui-text-area__root'data-disableddata-focusdata-invaliddata-part'root'data-scope'text-area'data-size| 'sm'
| 'md'
| 'lg'
q-text-area-label
| Attribute / Property | Value |
|---|---|
class | 'qui-text-area__label' |
data-disabled | |
data-focus | |
data-invalid | |
data-part | 'label' |
data-scope | 'text-area' |
data-size | | 'sm' |
class'qui-text-area__label'data-disableddata-focusdata-invaliddata-part'label'data-scope'text-area'data-size| 'sm'
| 'md'
| 'lg'
q-text-area-hint
| Attribute / Property | Value |
|---|---|
class | 'qui-text-area__hint' |
data-disabled | |
data-part | 'hint' |
data-scope | 'text-area' |
hidden | boolean |
class'qui-text-area__hint'data-disableddata-part'hint'data-scope'text-area'hiddenbooleanq-text-area-counter
<div>
element by default.| Attribute / Property | Value |
|---|---|
class | 'qui-text-area__counter' |
data-disabled | |
data-focus | |
data-invalid | |
data-max | number |
data-part | 'counter' |
data-scope | 'text-area' |
data-size | | 'sm' |
class'qui-text-area__counter'data-disableddata-focusdata-invaliddata-maxnumberdata-part'counter'data-scope'text-area'data-size| 'sm'
| 'md'
| 'lg'
q-text-area-input
ngModel
or formControl to this element. Apply them to the root element instead.| Prop | Type |
|---|---|
string |
string| Attribute / Property | Value |
|---|---|
class | 'qui-text-area__input' |
data-disabled | |
data-empty | |
data-focus | |
data-invalid | |
data-part | 'input' |
data-readonly | |
data-scope | 'text-area' |
data-size | | 'sm' |
class'qui-text-area__input'data-disableddata-emptydata-focusdata-invaliddata-part'input'data-readonlydata-scope'text-area'data-size| 'sm'
| 'md'
| 'lg'
q-text-area-error-text
| Attribute / Property | Value |
|---|---|
class | 'qui-text-area__error-text' |
data-part | 'error-text' |
data-scope | 'text-area' |
hidden | boolean |
class'qui-text-area__error-text'data-part'error-text'data-scope'text-area'hiddenboolean