Skip to content

bug: (textarea) initial value leaves caret at start unlike ion-input #31579

Description

@theguitou

Prerequisites

Ionic Framework Version

v9.x, v8.x

Current Behavior

When a value is assigned before the first render, setFocus() places the caret at the beginning of ion-textarea, but at the end of ion-input.

Expected Behavior

Initial caret positioning should be consistent with ion-input, without overriding an existing selection on subsequent focus calls.

Steps to Reproduce

  1. Create an ion-input and an ion-textarea, both initialized with "Hello world".
  2. Once rendered, call setFocus() on the ion-input: the caret appears at the end.
  3. Call setFocus() on the ion-textarea: the caret appears at the beginning.

Code Reproduction URL

https://stackblitz.com/edit/dgbjpfha

Ionic Info

Ionic CLI : 7.2.1
Ionic Framework : @ionic/angular 8.7.11
@angular-devkit/build-angular : 20.3.13
@angular-devkit/schematics : 20.3.15
@angular/cli : 20.3.15
@ionic/angular-toolkit : 12.3.0

Additional Information

Workaround

Explicitly position the caret after focus:

await textarea.setFocus();
const nativeTextarea = await textarea.getInputElement();
nativeTextarea.setSelectionRange(nativeTextarea.value.length, nativeTextarea.value.length);

Suggested Fix

In textarea.tsx, the native textarea receives its value as a text child, whereas input.tsx uses the native value property:

<textarea>{value}</textarea>

Use the same property-based approach as ion-input, keeping all other attributes unchanged:

<textarea value={value} />

We tested this change in the installed Ionic 8.7.11 bundle (@ionic/core/dist/esm/ion-textarea.entry.js): add value: value to the native textarea properties and remove the value child argument.

In an isolated browser test without the workaround, the caret then starts at 7, and an existing selection survives an unrelated render. The patch also resolved the reported application behavior.

Activity

  1. thetaPC commented on Oct 22, 2026

    @thetaPC
    Contributor

    Thanks for the report!

    Verified on 9.0.9. ion-textarea passes its starting value to the native <textarea> as text content, while ion-input sets the native value property. Browsers only move the caret to the end when the value property is set, so a textarea that has never been focused keeps its caret at position 0, and setFocus() focuses it there.

    Your workaround works. Run it on the first focus only: if it runs on every setFocus() call, it overwrites a selection the user made before the field lost focus.

    let caretPlaced = false;
    
    async function focusTextarea(textarea: HTMLIonTextareaElement) {
      await textarea.setFocus();
      if (!caretPlaced) {
        const native = await textarea.getInputElement();
        native.setSelectionRange(native.value.length, native.value.length);
        caretPlaced = true;
      }
    }

    Tracked as a bug in core.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions