Skip to main content

VTextarea

The VTextarea component provides a multi-line text input field with features like auto-grow, character counter, and validation.

Basic Usage

<template>
  <VTextarea
    v-model="message"
    label="Message"
  />
</template>

<script setup>
import { ref } from 'vue'

const message = ref('')
</script>

Props

modelValue
string
The text value of the textarea.
label
string
Label text for the textarea.
placeholder
string
Placeholder text.
rows
number | string
default:"5"
Number of rows to display.
autoGrow
boolean
default:"false"
Automatically grow the textarea to fit content.
noResize
boolean
default:"false"
Disable manual resizing of the textarea.
maxRows
number | string
Maximum number of rows when auto-grow is enabled.
maxHeight
number | string
Maximum height in pixels when auto-grow is enabled.
counter
boolean | number | string
Display a character counter. Pass a number to set max length.
counterValue
(value: any) => number
Function to compute the counter value.
persistentCounter
boolean
default:"false"
Always show the counter instead of only when focused.
persistentPlaceholder
boolean
default:"false"
Always show the placeholder.
prefix
string
Text to prepend to the input.
suffix
string
Text to append to the input.
clearable
boolean
default:"false"
Add a clear icon to remove the text.
disabled
boolean
default:"false"
Disable the textarea.
readonly
boolean
default:"false"
Make the textarea readonly.
autofocus
boolean
default:"false"
Automatically focus the textarea when mounted.

Auto Grow

<template>
  <VTextarea
    v-model="message"
    label="Auto-grow textarea"
    auto-grow
    rows="3"
    max-rows="10"
  />
</template>

<script setup>
import { ref } from 'vue'

const message = ref('')
</script>

Character Counter

<template>
  <div>
    <!-- Simple counter -->
    <VTextarea
      v-model="message1"
      label="With counter"
      counter
    />
    
    <!-- Counter with max length -->
    <VTextarea
      v-model="message2"
      label="Max 100 characters"
      :counter="100"
      :rules="[v => v.length <= 100 || 'Max 100 characters']"
    />
    
    <!-- Always visible counter -->
    <VTextarea
      v-model="message3"
      label="Persistent counter"
      counter
      persistent-counter
    />
  </div>
</template>

<script setup>
import { ref } from 'vue'

const message1 = ref('')
const message2 = ref('')
const message3 = ref('')
</script>

No Resize

<template>
  <VTextarea
    v-model="message"
    label="Cannot be resized"
    no-resize
    rows="4"
  />
</template>

<script setup>
import { ref } from 'vue'

const message = ref('')
</script>

With Validation

<template>
  <VForm>
    <VTextarea
      v-model="bio"
      label="Biography"
      :counter="200"
      :rules="[
        v => !!v || 'Bio is required',
        v => v.length >= 10 || 'Bio must be at least 10 characters',
        v => v.length <= 200 || 'Bio must be less than 200 characters'
      ]"
      auto-grow
      rows="3"
    />
  </VForm>
</template>

<script setup>
import { ref } from 'vue'

const bio = ref('')
</script>

Custom Row Count

<template>
  <div>
    <VTextarea
      v-model="message1"
      label="3 rows"
      rows="3"
    />
    
    <VTextarea
      v-model="message2"
      label="10 rows"
      rows="10"
    />
  </div>
</template>

<script setup>
import { ref } from 'vue'

const message1 = ref('')
const message2 = ref('')
</script>

With Prefix and Suffix

<template>
  <VTextarea
    v-model="comment"
    label="Comment"
    prefix="Note:"
    suffix="(optional)"
    auto-grow
  />
</template>

<script setup>
import { ref } from 'vue'

const comment = ref('')
</script>

Auto Grow with Constraints

<template>
  <VTextarea
    v-model="message"
    label="Constrained auto-grow"
    auto-grow
    rows="2"
    max-rows="8"
    hint="Grows from 2 to 8 rows"
    persistent-hint
  />
</template>

<script setup>
import { ref } from 'vue'

const message = ref('')
</script>

Clearable

<template>
  <VTextarea
    v-model="message"
    label="Clearable textarea"
    clearable
    auto-grow
  />
</template>

<script setup>
import { ref } from 'vue'

const message = ref('This text can be cleared')
</script>

Events

update:modelValue
(value: string) => void
Emitted when the textarea value changes.
update:focused
(focused: boolean) => void
Emitted when the focus state changes.
update:rows
(rows: number) => void
Emitted when the row count changes (auto-grow mode).
click:control
(e: MouseEvent) => void
Emitted when the control area is clicked.
mousedown:control
(e: MouseEvent) => void
Emitted when mousedown occurs on the control area.

Slots

counter
{}
Customize the counter display.
details
{}
Customize the details area (below the input).

Build docs developers (and LLMs) love