How to Listen to on-change and on-complete Events in vue3-otp-input
To capture real-time OTP input changes and completion states in vue3-otp-input, bind the @on-change and @on-complete event listeners to the component; these events emit the current OTP string value after every keystroke and when the input length matches the numInputs prop.
The vue3-otp-input library by ejirocodes provides a Vue 3 composition-API-based component for one-time password entry. Understanding how to listen to its on-change and on-complete events is essential for implementing real-time validation, auto-submission, and user feedback mechanisms.
Event Architecture in vue3-otp-input
The component defines three custom events using Vue 3's defineEmits macro in src/components/vue3-otp-input.vue (lines 45-49):
| Event | Payload | When it fires |
|---|---|---|
update:value |
string |
Every time the internal OTP string changes (used for v-model). |
on-change |
string |
After each individual character is entered, deleted or pasted. |
on-complete |
string |
When the OTP reaches the expected length (numInputs). |
How on-change and on-complete Work Internally
The on-change Event
Whenever a user interacts with the OTP fields, the component updates its internal reactive otp array. After each mutation, the code explicitly emits the on-change event with the joined string value (lines 106-108 in src/components/vue3-otp-input.vue):
emit("update:value", otp.value.join(""));
emit("on-change", otp.value.join(""));
This ensures parent components receive the current OTP state after every keystroke, paste action, or deletion.
The on-complete Event
The component tracks completion through the checkFilledAllInputs helper function. When the joined otp string length matches the numInputs prop, the function emits on-complete (lines 80-82 in src/components/vue3-otp-input.vue):
const checkFilledAllInputs = () => {
if (otp.value.join("").length === numInputs) {
emit("on-complete", otp.value.join(""));
}
};
This event is particularly useful for triggering automatic form submission or validation checks without requiring an explicit user action beyond completing the input.
Implementation Examples
Basic Event Listeners
The canonical usage pattern, as demonstrated in src/App.vue (lines 44-46), involves binding handlers directly in the parent template:
<template>
<vue3-otp-input
v-model:value="otp"
:num-inputs="6"
@on-change="handleOnChange"
@on-complete="handleOnComplete"
/>
</template>
<script setup>
import { ref } from 'vue';
import Vue3OtpInput from 'vue3-otp-input';
const otp = ref('');
const handleOnChange = (value) => {
console.log('Current OTP:', value);
};
const handleOnComplete = (value) => {
console.log('Completed OTP:', value);
// Trigger API verification here
};
</script>
Accessing Component Methods with Event Handling
For scenarios requiring programmatic control alongside event listening, combine template refs with event handlers:
<script setup lang="ts">
import { ref } from 'vue';
import Vue3OtpInput from 'vue3-otp-input';
const otpRef = ref<InstanceType<typeof Vue3OtpInput> | null>(null);
const otp = ref('');
function onComplete(value: string) {
console.log('Auto-submitting:', value);
// API call logic
}
function clearInput() {
otpRef.value?.clearInput();
}
</script>
<template>
<button @click="clearInput">Clear OTP</button>
<Vue3OtpInput
ref="otpRef"
v-model:value="otp"
:num-inputs="4"
@on-complete="onComplete"
/>
</template>
Handling Numeric Input Types
When restricting input to numbers, the events emit after validation:
<template>
<Vue3OtpInput
v-model:value="numericOtp"
input-type="number"
:num-inputs="5"
@on-change="val => console.log('Digits:', val)"
@on-complete="val => verifyNumericCode(val)"
/>
</template>
The component validates pasted data against the inputType prop before emitting events (lines 19-27 in src/components/vue3-otp-input.vue).
Summary
on-changefires after every character entry, deletion, or paste, emitting the current OTP string value.on-completetriggers only when the OTP length matches thenumInputsprop, indicating the user has finished entering the code.- Both events are declared in
src/components/vue3-otp-input.vueusingdefineEmitsand can be bound using Vue's@shorthand. - The events are useful for real-time validation, logging, and automatic form submission upon OTP completion.
Frequently Asked Questions
What is the difference between update:value and on-change in vue3-otp-input?
The update:value event is intended for v-model synchronization and fires whenever the OTP value changes, while on-change is a semantic event designed for parent components to react to user input changes. Both emit the current OTP string, but on-change is more appropriate for triggering side effects like validation or analytics tracking.
How do I trigger an action when the user finishes entering the OTP?
Bind a handler to the @on-complete event, which fires when the joined OTP string length equals the numInputs prop. This event emits the final OTP value, making it ideal for triggering API verification calls or automatic form submission without requiring an additional button click.
Can I listen to these events when using the component as a custom input?
Yes, the events are exposed through the component's defineEmits declaration and can be accessed regardless of how you import or register the component. Whether using global registration, local import, or wrapping the component in a custom input wrapper, the @on-change and @on-complete listeners function identically as long as the component instance is properly rendered in the template.
Why is my on-complete event not firing?
The on-complete event only fires when the OTP value length strictly equals the numInputs prop value. If the event is not firing, verify that numInputs is set correctly and that the user has filled all input fields. Additionally, ensure you are listening to the correct event name (@on-complete with a hyphen, not camelCase) in your Vue template.
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 →