ion-textarea
The textarea component is used for multi-line text input. A native textarea element is rendered inside of the component. The user experience and interactivity of the textarea component is improved by having control over the native textarea.
Unlike the native textarea element, the Ionic textarea does not support loading its value from the inner content. The textarea value should be set in the value
attribute.
The textarea component accepts the native textarea attributes in addition to the Ionic properties.
Basic Usage
Labels
Labels should be used to describe the textarea. They can be used visually, and they will also be read out by screen readers when the user is focused on the textarea. This makes it easy for the user to understand the intent of the textarea. Textarea has several ways to assign a label:
label
property: used for plaintext labelslabel
slot: used for custom HTML labels (experimental)aria-label
: used to provide a label for screen readers but adds no visible label
Label Placement
Labels will take up the width of their content by default. Developers can use the labelPlacement
property to control how the label is placed relative to the control.
Label Slot (experimental)
While plaintext labels should be passed in via the label
property, if custom HTML is needed, it can be passed through the label
slot instead.
Note that this feature is considered experimental because it relies on a simulated version of Web Component slots. As a result, the simulated behavior may not exactly match the native slot behavior.
No Visible Label
If no visible label is needed, developers should still supply an aria-label
so the textarea is accessible to screen readers.
Filled Textareas
Material Design offers filled styles for a textarea. The fill
property on the item can be set to either "solid"
or "outline"
.
Since the fill
styles visually defines the textarea container, textareas that use fill
should not be used in ion-item
.
Filled textareas can be used on iOS by setting Textarea's mode
to md
.
Helper & Error Text
Helper and error text can be used inside of a textarea with the helperText
and errorText
property. The error text will not be displayed unless the ion-invalid
and ion-touched
classes are added to the ion-textarea
. This ensures errors are not shown before the user has a chance to enter data.
In Angular, this is done automatically through form validation. In JavaScript, React and Vue, the class needs to be manually added based on your own validation.
Textarea Counter
The textarea counter is text that displays under a textarea to notify the user of how many characters have been entered out of the total that the textarea will accept. When adding counter, the default behavior is to format the value that gets displayed as inputLength
/ maxLength
. This behavior can be customized by passing in a formatter function to the counterFormatter
property.
Autogrow
When the autoGrow
property is set to true
, the textarea will grow and shrink based on its contents.
Clear on Edit
Setting the clearOnEdit
property to true
will clear the textarea after it has been blurred and then typed in again.
Migrating from Legacy Textarea Syntax
A simpler textarea syntax was introduced in Ionic 7.0. This new syntax reduces the boilerplate required to setup an textarea, resolves accessibility issues, and improves the developer experience.
Developers can perform this migration one textarea at a time. While developers can continue using the legacy syntax, we recommend migrating as soon as possible.
Using the Modern Syntax
Using the modern syntax involves three steps:
- Remove
ion-label
and use thelabel
property onion-textarea
instead. The placement of the label can be configured using thelabelPlacement
property onion-textarea
. - Move textarea-specific properties from
ion-item
on toion-textarea
. This includes thecounter
,counterFormatter
,fill
, andshape
properties. - Remove usages of the
helper
anderror
slots onion-item
and use thehelperText
anderrorText
properties onion-textarea
instead.
- JavaScript
- Angular
- React
- Vue
<!-- Label and Label Position -->
<!-- Before -->
<ion-item>
<ion-label position="floating">Label:</ion-label>
<ion-textarea></ion-textarea>
</ion-item>
<!-- After -->
<ion-item>
<ion-textarea label="Label:" label-placement="floating"></ion-textarea>
</ion-item>
<!-- Fill -->
<!-- Before -->
<ion-item fill="outline" shape="round">
<ion-label position="floating">Label:</ion-label>
<ion-textarea></ion-textarea>
</ion-item>
<!-- After -->
<!-- Textareas using `fill` should not be placed in ion-item -->
<ion-textarea fill="outline" shape="round" label="Label:" label-placement="floating"></ion-textarea>
<!-- Textarea-specific features on ion-item -->
<!-- Before -->
<ion-item counter="true">
<ion-label position="floating">Label:</ion-label>
<ion-textarea maxlength="100"></ion-textarea>
<div slot="helper">Enter text</div>
<div slot="error">Please enter text</div>
</ion-item>
<!-- After -->
<!--
Metadata such as counters and helper text should not
be used when a textarea is in an item/list. If you need to
provide more context on a textarea, consider using an ion-note
underneath the ion-list.
-->
<ion-textarea
label="Label:"
counter="true"
maxlength="100"
helper-text="Enter text"
error-text="Please enter text"
></ion-textarea>
<!-- Label and Label Position -->
<!-- Before -->
<ion-item>
<ion-label position="floating">Label:</ion-label>
<ion-textarea></ion-textarea>
</ion-item>
<!-- After -->
<ion-item>
<ion-textarea label="Label:" labelPlacement="floating"></ion-textarea>
</ion-item>
<!-- Fill -->
<!-- Before -->
<ion-item fill="outline" shape="round">
<ion-label position="floating">Label:</ion-label>
<ion-textarea></ion-textarea>
</ion-item>
<!-- After -->
<!-- Textareas using `fill` should not be placed in ion-item -->
<ion-textarea fill="outline" shape="round" label="Label:" labelPlacement="floating"></ion-textarea>
<!-- Textarea-specific features on ion-item -->
<!-- Before -->
<ion-item [counter]="true">
<ion-label position="floating">Label:</ion-label>
<ion-textarea maxlength="100"></ion-textarea>
<div slot="helper">Enter text</div>
<div slot="error">Please enter text</div>
</ion-item>
<!-- After -->
<!--
Metadata such as counters and helper text should not
be used when a textarea is in an item/list. If you need to
provide more context on a textarea, consider using an ion-note
underneath the ion-list.
-->
<ion-textarea
label="Label:"
[counter]="true"
maxlength="100"
helperText="Enter text"
errorText="Please enter text"
></ion-textarea>
{/* Label and Label Position */}
{/* Before */}
<IonItem>
<IonLabel position="floating">Label:</IonLabel>
<IonTextarea></IonTextarea>
</IonItem>
{/* After */}
<IonItem>
<IonTextarea label="Label:" labelPlacement="floating"></IonTextarea>
</IonItem>
{/* Fill */}
{/* Before */}
<IonItem fill="outline" shape="round">
<IonLabel position="floating">Label:</IonLabel>
<IonTextarea></IonTextarea>
</IonItem>
{/* After */}
{/* Textareas using `fill` should not be placed in IonItem */}
<IonTextarea fill="outline" shape="round" label="Label:" labelPlacement="floating"></IonTextarea>
{/* Textarea-specific features on IonItem */}
{/* Before */}
<IonItem counter={true}>
<IonLabel position="floating">Label:</IonLabel>
<IonTextarea maxlength="100"></IonTextarea>
<div slot="helper">Enter text</div>
<div slot="error">Please enter text</div>
</IonItem>
{/* After */}
{/*
Metadata such as counters and helper text should not
be used when a textarea is in an item/list. If you need to
provide more context on a textarea, consider using an IonNote
underneath the IonList.
*/}
<IonTextarea
label="Label:"
counter={true}
maxlength="100"
helperText="Enter text"
errorText="Please enter text"
></IonTextarea>
<!-- Label and Label Position -->
<!-- Before -->
<ion-item>
<ion-label position="floating">Label:</ion-label>
<ion-textarea></ion-textarea>
</ion-item>
<!-- After -->
<ion-item>
<ion-textarea label="Label:" label-placement="floating"></ion-textarea>
</ion-item>
<!-- Fill -->
<!-- Before -->
<ion-item fill="outline" shape="round">
<ion-label position="floating">Label:</ion-label>
<ion-textarea></ion-textarea>
</ion-item>
<!-- After -->
<!-- Textareas using `fill` should not be placed in ion-item -->
<ion-textarea fill="outline" shape="round" label="Label:" label-placement="floating"></ion-textarea>
<!-- Textarea-specific features on ion-item -->
<!-- Before -->
<ion-item :counter="true">
<ion-label position="floating">Label:</ion-label>
<ion-textarea maxlength="100"></ion-textarea>
<div slot="helper">Enter text</div>
<div slot="error">Please enter text</div>
</ion-item>
<!-- After -->
<!--
Metadata such as counters and helper text should not
be used when a textarea is in an item/list. If you need to
provide more context on a textarea, consider using an ion-note
underneath the ion-list.
-->
<ion-textarea
label="Label:"
:counter="true"
maxlength="100"
helper-text="Enter text"
error-text="Please enter text"
></ion-textarea>
Using the Legacy Syntax
Ionic uses heuristics to detect if an app is using the modern textarea syntax. In some instances, it may be preferable to continue using the legacy syntax. Developers can set the legacy
property on ion-textarea
to true
to force that instance of the textarea to use the legacy syntax.
Theming
Interfaces
TextareaChangeEventDetail
interface TextareaChangeEventDetail {
value?: string | null;
}
TextareaCustomEvent
While not required, this interface can be used in place of the CustomEvent
interface for stronger typing with Ionic events emitted from this component.
interface TextareaCustomEvent extends CustomEvent {
detail: TextareaChangeEventDetail;
target: HTMLIonTextareaElement;
}