# How to Handle Paste Events for OTP Input with Automatic Field Population in Vue 3

> Effortlessly handle paste events for OTP input in Vue 3. The vue3-otp-input component auto-validates, populates fields, and emits the value for seamless integration. Learn more!

- Repository: [Ejiro Asiuwhu/vue3-otp-input](https://github.com/ejirocodes/vue3-otp-input)
- Tags: how-to-guide
- Published: 2026-03-01

---

**The vue3-otp-input component automatically intercepts paste events, validates the clipboard data against your configured input type, distributes characters across remaining fields, and emits the completed value without requiring manual event listeners.**

Handling paste events for one-time password (OTP) inputs requires careful coordination between individual input fields and the parent component. The `vue3-otp-input` library implements a robust paste handling mechanism that works across desktop and mobile browsers, including a specific workaround for iOS SMS autofill. This guide explains the architectural flow, implementation details, and practical usage based on the actual source code in the ejirocodes/vue3-otp-input repository.

## Architecture of Paste Handling in vue3-otp-input

### Component Hierarchy and Event Flow

The library uses a two-layer architecture to manage paste events:

- **Wrapper component** ([`src/components/vue3-otp-input.vue`](https://github.com/ejirocodes/vue3-otp-input/blob/main/src/components/vue3-otp-input.vue)): Manages the `otp` array, tracks the `activeInput` index, and implements the main `handleOnPaste` logic.
- **Single input component** ([`src/components/single-otp-input.vue`](https://github.com/ejirocodes/vue3-otp-input/blob/main/src/components/single-otp-input.vue)): Renders individual digit fields and forwards paste events, including synthetic events for iOS compatibility.

When a user pastes content, the single input captures the native event and emits it to the wrapper, which then processes the clipboard data, validates it, and distributes values across the OTP array.

### The Paste Handling Flow

The `handleOnPaste` function in the wrapper component executes the following sequence:

1. **Prevent default behavior** to stop browser-native pasting into a single field.
2. **Extract clipboard data** using `event.clipboardData.getData("text/plain")`, truncated to the number of remaining empty slots (`numInputs - activeInput`).
3. **Validate input type** against configured `inputType` (number, letter-numeric, etc.) using regex patterns.
4. **Merge with existing data** by concatenating already-entered characters with the new pasted values.
5. **Update OTP array** and shift focus to the next empty field using `focusInput`.
6. **Emit completion events** (`update:value` and `on-complete`) when all fields are filled.

## Implementation Details and Source Code

### Wrapper Paste Logic in vue3-otp-input.vue

The main paste handler resides in [`src/components/vue3-otp-input.vue`](https://github.com/ejirocodes/vue3-otp-input/blob/main/src/components/vue3-otp-input.vue). Here is the core implementation:

```typescript
const handleOnPaste = (event: any) => {
  event.preventDefault();
  const pastedData = event.clipboardData
    .getData("text/plain")
    .slice(0, props.numInputs - activeInput.value)
    .split("");

  // Type-specific validation
  if (props.inputType === "number" && !pastedData.join("").match(/^\d+$/)) {
    return "Invalid pasted data";
  }
  if (props.inputType === "letter-numeric" && !pastedData.join("").match(/^\w+$/)) {
    return "Invalid pasted data";
  }

  // Merge with already-filled characters and write back
  const currentCharsInOtp = otp.value.slice(0, activeInput.value);
  const combinedWithPastedData = currentCharsInOtp.concat(pastedData);
  combinedWithPastedData.slice(0, props.numInputs).forEach((value, i) => {
    otp.value[i] = value;
  });

  // Focus next empty input and emit change/completion events
  focusInput(combinedWithPastedData.slice(0, props.numInputs).length);
  return checkFilledAllInputs();
};

```

This function handles edge cases such as partial pastes (pasting "12" into the third field of a six-digit OTP) and over-length pastes (truncating "123456789" to fit remaining slots).

### iOS SMS Autofill Workaround in single-otp-input.vue

Mobile Safari's SMS autofill does not always fire standard paste events. The component in [`src/components/single-otp-input.vue`](https://github.com/ejirocodes/vue3-otp-input/blob/main/src/components/single-otp-input.vue) detects multi-character inputs and synthesizes a clipboard event:

```typescript
if (value && value.trim().length > 1) {
  // iOS does not fire a native onPaste when SMS autofills.
  // Create a synthetic clipboard event so the wrapper can handle it.
  e.clipboardData = {
    getData: () => value.trim(),
  };
  return emit("on-paste", e as ClipboardEvent);
}
return emit("on-change", value);

```

When detected, it constructs a synthetic `ClipboardEvent` with a `getData` method returning the autofilled value, then emits this as an `on-paste` event. This ensures that iOS users experience the same automatic field population as desktop users who manually paste.

## Practical Usage Example

To enable automatic field population via paste events, install the component and bind it to your form:

```bash
npm install vue3-otp-input

```

Then implement the component in your Vue 3 template:

```vue
<template>
  <Vue3OtpInput
    v-model="otpCode"
    :numInputs="6"
    inputType="number"
    separator="-"
    shouldAutoFocus
    @on-complete="handleComplete"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue';
import Vue3OtpInput from 'vue3-otp-input';

const otpCode = ref('');
const handleComplete = (value: string) => {
  console.log('OTP completed:', value);
  // Submit to verification API
};
</script>

```

**Behavior when pasting "123456":**

1. User pastes into any input field (or iOS autofills).
2. `single-otp-input` captures the event and forwards it to the wrapper.
3. `handleOnPaste` validates the numeric format, splits the string, and populates `otp` array indices 0-5.
4. Focus shifts to the final field.
5. `on-complete` event fires with value `"123456"`, and `v-model` updates simultaneously.

## Handling Edge Cases

The component automatically manages several paste scenarios without additional configuration:

- **Partial paste**: Pasting "45" into the third field of a six-digit OTP fills slots 2 and 3, leaving slots 4-5 empty for manual entry.
- **Over-length paste**: Pasting "123456789" into a 6-digit input truncates to "123456", discarding excess characters.
- **Invalid characters**: When `inputType="number"`, pasting "12ab34" aborts the operation and returns "Invalid pasted data", leaving existing inputs unchanged.
- **iOS SMS autofill**: The synthetic event workaround ensures auto-populated codes from text messages trigger the same distribution logic as manual pastes.

## Summary

- **Automatic distribution**: The `handleOnPaste` function in [`src/components/vue3-otp-input.vue`](https://github.com/ejirocodes/vue3-otp-input/blob/main/src/components/vue3-otp-input.vue) intercepts clipboard data, validates it against the configured `inputType`, and distributes characters across the OTP array.
- **iOS compatibility**: [`src/components/single-otp-input.vue`](https://github.com/ejirocodes/vue3-otp-input/blob/main/src/components/single-otp-input.vue) detects multi-character SMS autofill events and synthesizes a `ClipboardEvent` to ensure consistent handling across platforms.
- **Zero configuration**: Paste handling works immediately upon installing the component, managing edge cases like partial pastes, over-length strings, and invalid characters automatically.
- **Event emission**: Successful paste operations trigger `update:value` for `v-model` binding and `on-complete` when all fields are filled, enabling seamless form integration.

## Frequently Asked Questions

### How does vue3-otp-input handle paste events differently from native HTML inputs?

Unlike standard HTML inputs that paste content into a single field, **vue3-otp-input** intercepts the paste event at the wrapper level via `handleOnPaste` in [`src/components/vue3-otp-input.vue`](https://github.com/ejirocodes/vue3-otp-input/blob/main/src/components/vue3-otp-input.vue). It extracts the clipboard data, validates it against the `inputType` regex (number or letter-numeric), splits the string into individual characters, and distributes them across the remaining empty input slots. This ensures that pasting "123456" into any field of a 6-digit OTP automatically fills all six fields sequentially.

### Why is there a special workaround for iOS SMS autofill in the single-otp-input component?

iOS Safari's SMS autofill feature does not consistently fire native `paste` events when suggesting OTP codes from messages. To handle this, [`src/components/single-otp-input.vue`](https://github.com/ejirocodes/vue3-otp-input/blob/main/src/components/single-otp-input.vue) monitors input changes for values longer than one character. When detected, it constructs a synthetic `ClipboardEvent` with a `getData` method returning the autofilled value, then emits this as an `on-paste` event. This ensures that iOS users experience the same automatic field population as desktop users who manually paste.

### What happens when a user pastes more characters than remaining OTP fields?

The `handleOnPaste` function automatically truncates over-length paste data to fit the remaining available slots. Specifically, it slices the clipboard string using `props.numInputs - activeInput.value`, ensuring that only enough characters to fill the empty fields are processed. For example, pasting "123456789" into the first field of a 6-digit OTP will only use "123456", discarding the excess "789" without error or notification to the user.

### How can I validate pasted content before it populates the OTP fields?

The component performs built-in validation based on the `inputType` prop. When `inputType` is set to `"number"`, the paste handler checks if the clipboard data matches `/^\d+$/` (digits only). For `"letter-numeric"`, it validates against `/^\w+$/` (alphanumeric). If validation fails, the function returns `"Invalid pasted data"` and aborts the operation, leaving existing inputs unchanged. For custom validation logic, you would need to fork the component and modify the `handleOnPaste` function in [`src/components/vue3-otp-input.vue`](https://github.com/ejirocodes/vue3-otp-input/blob/main/src/components/vue3-otp-input.vue) before the standard validation checks.