This problem occurs because type=”number” in HTML input has inconsistent behavior across browsers and still allows some non-numeric characters to pass through, including the letter “e” (which is interpreted as exponential notation in numbers).
Some solutions you can use:
Solution 1: Use type=”tel” for phone numbers
<Input
type="tel"
name="no_hp"
value={form.no_hp}
onChange={handleChange}
autoComplete="off"
placeholder="Enter phone number"
className="rounded-lg border-slate-300 bg-white focus:border-blue-500 focus:ring-blue-500"
pattern="[0-9]*"
/>
Solution 2: Filter input di handler
const handleChange = (e) => {
const { name, value } = e.target;
if (name === 'no_hp') {
// Only allow numbers
const numericValue = value.replace(/[^0-9]/g, '');
setForm(prev => ({
...prev,
[name]: numericValue
}));
} else {
setForm(prev => ({
...prev,
[name]: value
}));
}
};
Solution 3: Combination of type=”text” with validation
<Input
type="text"
name="no_hp"
value={form.no_hp}
onChange={handleChange}
onKeyDown={(e) => {
// Block semua karakter kecuali angka dan tombol navigasi
if (!/[0-9]/.test(e.key) && !['Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'Tab'].includes(e.key)) {
e.preventDefault();
}
}}
autoComplete="off"
placeholder="Enter phone number"
className="rounded-lg border-slate-300 bg-white focus:border-blue-500 focus:ring-blue-500"
/>
Solution 4: Use inputMode
<Input
type="text"
inputMode="numeric"
name="no_hp"
value={form.no_hp}
onChange={handleChange}
autoComplete="off"
placeholder="Enter phone number"
className="rounded-lg border-slate-300 bg-white focus:border-blue-500 focus:ring-blue-500"
pattern="[0-9]*"
/>
Recommendation: For phone numbers, use Solution 1 (type=”tel”) as it is semantically more correct and on mobile devices will display a numeric keypad. Happy Coding!!!