Vue 3 OTP Input Component
vue3-otp-input is a fully customizable, one-time password (OTP) input component designed for Vue 3 applications, leveraging the Vue Composition API. The current stable version is `0.5.40`, with a consistent release cadence addressing bug fixes and minor enhancements. Key differentiators include robust handling of mobile autofill, improved focus behavior, and specific fixes for iOS input issues, which were addressed in recent `0.5.x` releases. It is a lightweight component that ships with TypeScript types, providing a seamless integration experience for developers building modern Vue applications requiring secure and user-friendly OTP entry forms.
Common errors
-
Failed to resolve component: OtpInput
cause The OtpInput component was not correctly imported or registered in your Vue application. This often happens if it's not imported as a default export or if there's a typo.fixEnsure you are using `import OtpInput from 'vue3-otp-input';` in your script section. If using options API, ensure it's registered in the `components` option: `components: { OtpInput }`. -
TypeError: Cannot read properties of undefined (reading 'length')
cause This error can occur if the `value` prop (or `v-model:value`) bound to `OtpInput` is not initialized or is not a string type, which the component expects for internal handling.fixInitialize your `v-model` bound variable to an empty string, e.g., `const otpValue = ref('');` or `data() { return { otpValue: '' }; }`. -
OTP input fields do not clear after submission or on button click.
cause While `v-model` handles the value, clearing the physical input fields requires calling a specific component method if `v-model` alone doesn't trigger a visual reset.fixUse a `ref` on the `OtpInput` component (e.g., `<OtpInput ref="otpInputRef" ... />`) and then call the `clearInput()` method: `otpInputRef.value?.clearInput();`.
Warnings
- breaking Version `0.5.0` included a 'major refactor leading to reduced bundle size' and a migration from `vue-cli` to `vite` for setup and type definition generation. While specific API breaks were not explicitly detailed beyond the `chore!: publish v0.5.0` commit message, users on older versions (pre-0.5.0) should review their build configurations and any deep imports if upgrading, as internal paths and module resolution may have changed.
- gotcha Past versions of `vue3-otp-input` had issues with pasting OTP codes, particularly from mobile autofill, and inconsistent focus behavior, especially on iOS devices. These issues could lead to a poor user experience where OTPs were incorrectly parsed or inputs were difficult to navigate.
- gotcha When using `v-model` with `vue3-otp-input`, some users reported duplicate values when inputting from the right or with specific `input-type` configurations in versions prior to `0.4.4`. This could result in incorrect OTP values being submitted.
Install
-
npm install vue3-otp-input -
yarn add vue3-otp-input -
pnpm add vue3-otp-input
Imports
- OtpInput
import { OtpInput } from 'vue3-otp-input'; // Common mistake, it's a default exportimport OtpInput from 'vue3-otp-input';
- Props
import type { OtpInputProps } from 'vue3-otp-input'; - CommonJS require
const OtpInput = require('vue3-otp-input');N/A (ESM recommended)
Quickstart
<template>
<div class="otp-container">
<h2>Enter OTP</h2>
<OtpInput
ref="otpInputRef"
v-model:value="otpValue"
:numInputs="6"
:shouldAutoFocus="true"
:input-type="['number', 'text']"
:input-classes="['otp-input']"
separator="-"
@on-change="handleOnChange"
@on-complete="handleOnComplete"
/>
<p v-if="otpValue">Current OTP: {{ otpValue }}</p>
<button @click="clearOtp">Clear OTP</button>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import OtpInput from 'vue3-otp-input';
const otpValue = ref<string>('');
const otpInputRef = ref<InstanceType<typeof OtpInput> | null>(null);
const handleOnChange = (value: string) => {
console.log('OTP Changed:', value);
};
const handleOnComplete = (value: string) => {
console.log('OTP Complete:', value);
alert(`OTP Completed: ${value}`);
// In a real application, you might submit the OTP here
};
const clearOtp = () => {
otpValue.value = '';
otpInputRef.value?.clearInput(); // Using the clearInput method exposed by the component
};
</script>
<style scoped>
.otp-container {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
padding: 20px;
border: 1px solid #eee;
border-radius: 8px;
max-width: 400px;
margin: 50px auto;
}
.otp-input {
width: 40px;
height: 40px;
padding: 5px;
margin: 0 5px;
text-align: center;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 1.2em;
}
.otp-input:focus {
border-color: #007bff;
outline: none;
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.25);
}
</style>