How to Use v-model with vue3-otp-input for Two-Way Data Binding
Use the named v-model syntax v-model:value="otpValue" to bind the OTP string reactively, because the component exposes a value prop and emits update:value events.
The vue3-otp-input library provides a customizable one-time password input component for Vue 3 applications. To integrate it seamlessly with your form state, you need to understand how to use v-model with vue3-otp-input for proper two-way data binding. This guide explains the internal contract between the component's props and events, sourced directly from the repository's implementation.
Understanding the v-model Contract in vue3-otp-input
The component implements Vue 3's custom v-model convention through a specific prop-event pair defined in src/components/vue3-otp-input.vue.
The value Prop
The component accepts a prop named value of type string (declared at lines 11-14). This prop represents the current OTP value controlled by the parent component.
The update:value Event
To communicate changes back to the parent, the component emits update:value using Vue 3's defineEmits macro (defined at lines 45-48). This event fires whenever the internal OTP array changes, such as when a user types or pastes a code.
Internal Synchronization
The component maintains an internal reactive otp array that syncs with the external value prop through a watcher (implemented at lines 55-63). When the parent updates the bound value, the watcher detects the change and updates the internal state, ensuring the UI reflects the new OTP string immediately.
Implementing Two-Way Binding with v-model:value
Because the component uses value instead of the default modelValue, you must use the named v-model syntax v-model:value.
Basic Usage Example
Here is the minimal implementation to bind a reactive reference to the OTP input:
<script setup lang="ts">
import { ref } from "vue";
import Vue3OtpInput from "vue3-otp-input";
const bindValue = ref(""); // Reactive OTP string
</script>
<template>
<vue3-otp-input
v-model:value="bindValue"
:num-inputs="6"
input-classes="otp-box"
/>
<p>Current OTP: {{ bindValue }}</p>
</template>
<style>
.otp-box {
width: 2.5rem;
text-align: center;
margin: 0 0.25rem;
}
</style>
In this example, every keystroke inside the OTP fields automatically updates bindValue, and the paragraph below displays the live value.
Advanced Usage with Events and Refs
For scenarios requiring programmatic control or event handling, combine v-model:value with component references and event listeners:
<script setup lang="ts">
import { ref, unref } from "vue";
import Vue3OtpInput from "vue3-otp-input";
const otpRef = ref<InstanceType<typeof Vue3OtpInput> | null>(null);
const bindValue = ref("");
function onComplete(val: string) {
console.log("OTP completed:", val);
// Trigger form submission or API call
}
function onChange(val: string) {
console.log("OTP changed:", val);
}
</script>
<template>
<vue3-otp-input
ref="otpRef"
v-model:value="bindValue"
:num-inputs="4"
separator="-"
inputType="letter-numeric"
:should-auto-focus="true"
@on-complete="onComplete"
@on-change="onChange"
/>
<div class="controls">
<button @click="unref(otpRef)?.clearInput()">Clear Input</button>
<button @click="unref(otpRef)?.fillInput('12AB')">Fill Input</button>
</div>
<p>Bound value: {{ bindValue }}</p>
</template>
This implementation demonstrates:
- Two-way binding via
v-model:valuekeepsbindValuesynchronized. - Programmatic control using
clearInput()andfillInput()methods exposed throughdefineExposein the component source (lines 13-16). - Event handling for
on-completeandon-changeto execute logic when the user finishes entering the code or modifies it.
Programmatic Control and Resetting Values
When you need to reset the OTP from the parent component, simply mutate the bound reactive reference. The component watches the value prop and synchronizes its internal otp array accordingly.
// In parent component
bindValue.value = ""; // Clears all input fields immediately
This works because of the watcher defined in src/components/vue3-otp-input.vue at lines 55-63, which detects external changes to the value prop and updates the internal state to match.
Summary
- Use the named v-model syntax
v-model:valueto bind data tovue3-otp-inputbecause the component exposes avalueprop and emitsupdate:valueevents. - The component implements full two-way binding: parent updates reflect in the UI, and user input updates the parent state.
- Access programmatic methods like
clearInput()andfillInput()by assigning a template ref to the component instance. - Reset the OTP by mutating the bound reactive value; the component automatically synchronizes its internal state via prop watchers defined in
src/components/vue3-otp-input.vue.
Frequently Asked Questions
Why does vue3-otp-input use v-model:value instead of standard v-model?
Vue 3's default v-model uses a prop named modelValue and an event named update:modelValue. However, vue3-otp-input was designed with an explicit value prop to match traditional input element APIs. Therefore, you must use the named v-model syntax v-model:value to tell Vue which prop to bind to. This is fully supported in Vue 3 and provides the same two-way binding behavior.
How do I clear the OTP input programmatically?
You have two options to clear the input. First, mutate the bound reactive reference directly: myOtpValue.value = "". This triggers the component's internal watcher and clears all fields. Alternatively, assign a template ref to the component and call the exposed clearInput() method: otpRef.value?.clearInput(). Both methods reset the internal otp array and update the UI immediately.
Can I use v-model with TypeScript and vue3-otp-input?
Yes, TypeScript support is fully available. Import the component type and use InstanceType<typeof Vue3OtpInput> when creating template refs. The v-model:value binding works with ref<string> types, and the component's emitted events are properly typed in the source. Ensure you import the component correctly: import Vue3OtpInput from "vue3-otp-input".
What happens if I change the bound value from the parent component?
When you update the reactive value bound to v-model:value from the parent, the component detects the change through its internal watcher on the value prop (defined at lines 55-63 in src/components/vue3-otp-input.vue). The watcher then updates the internal otp array to match the new string value, causing the individual input fields to update their display accordingly. This ensures the UI always stays synchronized with the parent state.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →