textarea

Displays a form textarea or a component that looks like a textarea.

PreviousNext
import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardTextareaComponent } from '@/shared/components/textarea/textarea.component';

@Component({
  selector: 'z-demo-textarea-preview',
  imports: [ZardTextareaComponent],
  template: `
    <textarea z-textarea id="textarea-preview" placeholder="Type your message here." class="w-72"></textarea>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoTextareaPreviewComponent {}

Installation

Copy
npx zard-cli@latest add textarea

Usage

import { ZardTextareaComponent } from '@/shared/components/textarea/textarea.component';
Copy
<textarea z-textarea rows="6" placeholder="Type your message"></textarea>
Copy

Examples

field

Wrap textarea[z-textarea] in z-field with a z-field-label and z-field-description to add a label and helper text.

Enter your message below.

import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardFieldImports } from '@/shared/components/field/field.imports';
import { ZardTextareaComponent } from '@/shared/components/textarea/textarea.component';

@Component({
  selector: 'z-demo-textarea-field',
  imports: [ZardTextareaComponent, ...ZardFieldImports],
  template: `
    <div z-field class="w-72">
      <label z-field-label for="textarea-message">Message</label>
      <p z-field-description>Enter your message below.</p>
      <textarea z-textarea id="textarea-message" placeholder="Type your message here."></textarea>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoTextareaFieldComponent {}

disabled

Set the native disabled attribute on textarea[z-textarea], and add data-disabled="true" to the surrounding z-field so its label dims along with the control.
import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardFieldImports } from '@/shared/components/field/field.imports';
import { ZardTextareaComponent } from '@/shared/components/textarea/textarea.component';

@Component({
  selector: 'z-demo-textarea-disabled',
  imports: [ZardTextareaComponent, ...ZardFieldImports],
  template: `
    <div z-field class="w-72" data-disabled="true">
      <label z-field-label for="textarea-disabled">Message</label>
      <textarea z-textarea id="textarea-disabled" placeholder="Type your message here." disabled></textarea>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoTextareaDisabledComponent {}

invalid

Set aria-invalid="true" on textarea[z-textarea] and data-invalid="true" on the surrounding z-field to mark the field as invalid; see the form example for wiring these attributes to a reactive form control.

Please enter a valid message.

import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardFieldImports } from '@/shared/components/field/field.imports';
import { ZardTextareaComponent } from '@/shared/components/textarea/textarea.component';

@Component({
  selector: 'z-demo-textarea-invalid',
  imports: [ZardTextareaComponent, ...ZardFieldImports],
  template: `
    <div z-field class="w-72" data-invalid="true">
      <label z-field-label for="textarea-invalid">Message</label>
      <textarea z-textarea id="textarea-invalid" placeholder="Type your message here." aria-invalid="true"></textarea>
      <p z-field-description>Please enter a valid message.</p>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoTextareaInvalidComponent {}

button

Pair textarea[z-textarea] with z-button to build a message box with a submit action.
import { ChangeDetectionStrategy, Component, signal } from '@angular/core';

import { ZardButtonComponent } from '@/shared/components/button/button.component';
import { ZardTextareaComponent } from '@/shared/components/textarea/textarea.component';

@Component({
  selector: 'z-demo-textarea-button',
  imports: [ZardTextareaComponent, ZardButtonComponent],
  template: `
    <div class="grid w-72 gap-2">
      <textarea
        z-textarea
        id="textarea-button-message"
        placeholder="Type your message here."
        [(value)]="message"
      ></textarea>
      <button type="button" z-button [zDisabled]="!message().trim()" (click)="send()">Send message</button>
      @if (sentMessage()) {
        <p class="text-muted-foreground text-sm" aria-live="polite">Sent: "{{ sentMessage() }}"</p>
      }
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoTextareaButtonComponent {
  protected readonly message = signal('');
  protected readonly sentMessage = signal('');

  protected send(): void {
    this.sentMessage.set(this.message());
    this.message.set('');
  }
}

form

A reactive form built from z-field and formControlName, with a live validation message on the feedback textarea once it's touched and invalid.

Share as much detail as you can.

import { ChangeDetectionStrategy, Component } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';

import { ZardButtonComponent } from '@/shared/components/button/button.component';
import { ZardFieldImports } from '@/shared/components/field/field.imports';
import { ZardTextareaComponent } from '@/shared/components/textarea/textarea.component';

@Component({
  selector: 'z-demo-textarea-form',
  imports: [ZardTextareaComponent, ZardButtonComponent, ReactiveFormsModule, ...ZardFieldImports],
  template: `
    <form class="grid w-72 gap-4" [formGroup]="form" (ngSubmit)="onSubmit()">
      @let feedbackControl = form.controls.feedback;
      @let feedbackInvalid = feedbackControl.invalid && feedbackControl.touched;
      <div z-field [attr.data-invalid]="feedbackInvalid || null">
        <label z-field-label for="textarea-form-feedback">Feedback</label>
        <textarea
          z-textarea
          id="textarea-form-feedback"
          placeholder="Tell us what you think..."
          formControlName="feedback"
          [attr.aria-invalid]="feedbackInvalid || null"
        ></textarea>
        @if (feedbackInvalid) {
          <z-field-error>
            @if (feedbackControl.hasError('required')) {
              Feedback is required.
            } @else if (feedbackControl.hasError('minlength')) {
              Feedback must be at least 10 characters.
            }
          </z-field-error>
        } @else {
          <p z-field-description>Share as much detail as you can.</p>
        }
      </div>
      <button z-button type="submit">Submit feedback</button>
    </form>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoTextareaFormComponent {
  protected readonly form = new FormGroup({
    feedback: new FormControl('', { nonNullable: true, validators: [Validators.required, Validators.minLength(10)] }),
  });

  protected onSubmit(): void {
    this.form.markAllAsTouched();
    if (this.form.valid) {
      console.log('Feedback submitted:', this.form.getRawValue());
    }
  }
}

rtl

To enable RTL support in zard/ui, see the RTL configuration guide.

أدخل رسالتك أدناه.

// You will notice this example is rendered inside a wrapper that sets the dir and data-lang attributes, and
// reads its text from a translations helper. This is because this site is not RTL by default.
// In your application you won't need either: set dir="rtl" on <html> (or use the CDK Dir directive on a subtree)
// and write the text of your own language. See the RTL guide: https://zardui.com/docs/rtl

import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardFieldImports } from '@/shared/components/field/field.imports';
import { ZardTextareaComponent } from '@/shared/components/textarea/textarea.component';
import { injectRtlTranslation, type ZardRtlTranslations } from '@/shared/demo-utils/rtl-translation';

const translations: ZardRtlTranslations<{ label: string; description: string; placeholder: string }> = {
  en: {
    dir: 'ltr',
    values: {
      label: 'Message',
      description: 'Enter your message below.',
      placeholder: 'Type your message here.',
    },
  },
  ar: {
    dir: 'rtl',
    values: {
      label: 'الرسالة',
      description: 'أدخل رسالتك أدناه.',
      placeholder: 'اكتب رسالتك هنا.',
    },
  },
  he: {
    dir: 'rtl',
    values: {
      label: 'הודעה',
      description: 'הזן את הודעתך למטה.',
      placeholder: 'הקלד את הודעתך כאן.',
    },
  },
};

@Component({
  selector: 'z-demo-textarea-rtl',
  imports: [ZardTextareaComponent, ...ZardFieldImports],
  template: `
    <div z-field class="w-72">
      <label z-field-label for="textarea-rtl-message">{{ i18n.t().label }}</label>
      <p z-field-description>{{ i18n.t().description }}</p>
      <textarea z-textarea id="textarea-rtl-message" [placeholder]="i18n.t().placeholder"></textarea>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoTextareaRtlComponent {
  protected readonly i18n = injectRtlTranslation(translations);
}

API Reference

textarea[z-textarea]Component

A directive that styles a native `<textarea>` element. All native HTML textarea attributes (`rows`, `placeholder`, `disabled`, `required`, `readonly`, `maxlength`, `aria-invalid`, etc.) keep working as-is; the control grows with its content via CSS `field-sizing: content`, with no dedicated auto-resize input and no built-in character-count display.

PropertyDescriptionTypeDefault
[class] Additional CSS classes ClassValue ''
[value] Textarea value, two-way bindable string ''
[(value)] Textarea value (two-way binding) string ''
github iconwhatsapp icondiscord iconX icon

Made with ❤ in Brazil. Open source and available on GitHub .