OTP Input Paste Support Implementation in JavaScript
Paste support is often forgotten but expected. Here is how to implement it correctly.
OTP Input Paste Support Implementation in JavaScript
Paste support is often forgotten but users expect it. Here is how to implement it correctly.
The Problem
Users often copy an OTP from an email or SMS and paste it into the OTP input. Without paste support, only the first box gets filled.
The Solution
input.addEventListener("paste", (e) => { e.preventDefault(); const pasted = e.clipboardData.getData("text").replace(/\D/g, ""); pasted.split("").forEach((char, i) => { if (index + i < inputs.length) { inputs[index + i].value = char; } }); const nextIndex = Math.min(index + pasted.length, inputs.length - 1); inputs[nextIndex].focus(); checkComplete(); }); `` ### How It Works 1. `e.preventDefault()`: prevent the default paste (which would fill only the current input). 2. `e.clipboardData.getData("text")`: get the pasted text. 3. `.replace(/\D/g, "")`: filter to numeric only. 4. `.split("")`: split into individual characters. 5. `.forEach()`: fill each input starting from the current index. 6. `Math.min()`: ensure we do not go beyond the last input. 7. Focus the last filled input. 8. Check if the OTP is complete. ### Edge Cases - Pasting more characters than inputs: only fill up to the number of inputs. - Pasting non-numeric characters: filter them out. - Pasting in the middle: fill from the current index, not the first. - Pasting an empty string: do nothing. ### Testing Paste 1. Copy a 4-digit number (e.g., "1234"). 2. Paste into any OTP input. 3. Verify all 4 inputs are filled. 4. Verify the verify button is enabled. ### The Takeaway Paste support: prevent default, get the pasted text, filter to numeric, split into characters, fill inputs starting from the current index, focus the last filled input, and check completion. Handle edge cases (too many chars, non-numeric, empty). This is often forgotten but expected by users.
Listen for the paste event, prevent default, get the pasted text from clipboardData, filter to numeric only with replace(/\D/g, ''), split into characters, and fill each input starting from the current index. Focus the last filled input and check completion.
Because the default paste would fill only the current input with the entire pasted string (which exceeds maxlength=1, so only the first character is kept). preventDefault lets you control how the pasted text is distributed across the inputs.
Check if index + i < inputs.length before filling each input: if (index + i < inputs.length) inputs[index + i].value = char. Extra characters are ignored. Focus the last input: Math.min(index + pasted.length, inputs.length - 1).
Use replace(/\D/g, '') on the pasted text: const pasted = e.clipboardData.getData('text').replace(/\D/g, ''). This removes all non-digit characters before splitting and filling the inputs.
From the current focused input's index, not always from the first. If the user pastes into the third input, fill from index 2: inputs[index + i].value = char. This matches user expectation.
Ready to master React completely?
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.
Master React
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course.

