Input Masking in Alpine.js: Teaching Your Text Boxes Good Manners 🎭
The Story of the Helpful Assistant
Imagine you have a robot friend who helps people fill out forms. But here’s the problem: people sometimes type things in messy ways!
- Someone types their phone number as
1234567890 - Another person types it as
123 456 7890 - Someone else tries
(123) 456-7890
Your robot friend gets confused! Which one is right?
Input masking is like teaching your robot friend to be a helpful guide. Instead of letting people type however they want, the robot gently says:
“Let me help you! Type your numbers, and I’ll put them in the right spots for you!”
What is Input Masking?
Think of input masking like training wheels for typing.
When you learned to ride a bike, training wheels kept you on track. Input masks do the same thing for text boxes—they keep your typing on track!
Without mask: User types anything → Messy data
With mask: User types → Mask formats it → Clean data
1. Basic Input Masking
The Simple Pattern Helper
Basic input masking is like a fill-in-the-blank game.
You create a pattern with special symbols:
9= Any number (0-9)a= Any letter (a-z)*= Any character
Example: Phone Number Mask
<input
x-data
x-mask="(999) 999-9999"
placeholder="(___) ___-____"
>
What happens:
- User types:
1234567890 - Mask shows:
(123) 456-7890
The mask automatically adds the parentheses, space, and dash!
How It Works (Simple Explanation)
graph TD A["User types a key"] --> B{Is it a number?} B -->|Yes| C["Put it in next empty 9 spot"] B -->|No| D["Ignore it!"] C --> E["Show formatted result"]
More Basic Examples
Date Mask:
<input x-mask="99/99/9999" placeholder="MM/DD/YYYY">
User types 12252024 → Shows 12/25/2024
Time Mask:
<input x-mask="99:99" placeholder="HH:MM">
User types 1430 → Shows 14:30
ZIP Code:
<input x-mask="99999" placeholder="12345">
Only allows exactly 5 numbers!
2. Dynamic Input Masks
Masks That Change Their Mind!
Sometimes, one pattern isn’t enough. What if someone’s phone number could be from different countries? Or what if a code can be short OR long?
Dynamic masks change based on what the user types!
Think of it like a magical coloring book that shows different pictures depending on which crayon you pick first!
Example: Credit Card Detection
Different credit cards have different patterns:
- Visa starts with 4
- Mastercard starts with 5
- Amex starts with 3
<input
x-data="{ cardMask: '9999 9999 9999 9999' }"
x-mask="cardMask"
@input="
if ($el.value.startsWith('3')) {
cardMask = '9999 999999 99999'
} else {
cardMask = '9999 9999 9999 9999'
}
"
>
How Dynamic Masks Work
graph TD A["User starts typing"] --> B["Check first characters"] B --> C{Which pattern matches?} C -->|Pattern A| D["Apply Mask A"] C -->|Pattern B| E["Apply Mask B"] C -->|Pattern C| F["Apply Mask C"]
Another Example: Flexible Phone Numbers
Some countries have different phone number lengths!
<input
x-data="{ phoneMask: '(999) 999-9999' }"
x-mask="phoneMask"
@input="
let digits = $el.value.replace(/\D/g, '');
if (digits.length > 10) {
phoneMask = '+9 (999) 999-9999'
} else {
phoneMask = '(999) 999-9999'
}
"
>
Magic! The mask grows when you type more numbers!
3. Money Input Formatting
Making Numbers Look Like Money!
Money is special. It needs:
- A currency symbol ($, €, £)
- Commas for thousands
- A decimal point for cents
- Maybe only 2 decimal places
Without formatting: 1000000
With formatting: $1,000,000.00
Much easier to read!
Simple Money Input
<input
x-data="{ amount: '' }"
x-model="amount"
@input="
let num = $el.value.replace(/[^0-9.]/g, '');
let parts = num.split('.');
parts[0] = parts[0].replace(
/\B(?=(\d{3})+(?!\d))/g, ','
);
if (parts[1]) parts[1] = parts[1].slice(0,2);
amount = '#x27; + parts.join('.');
"
placeholder="$0.00"
>
What This Does (Step by Step)
graph TD A["User types: 1234567"] --> B["Remove non-numbers"] B --> C["Split at decimal point"] C --> D["Add commas every 3 digits"] D --> E["Limit to 2 decimal places"] E --> F["Add $ symbol"] F --> G["Show: $1,234,567"]
Money Formatting Rules
| What | How | Example |
|---|---|---|
| Remove letters | Keep only 0-9 and . | $abc123 → 123 |
| Add commas | Every 3 digits from right | 1234567 → 1,234,567 |
| Limit decimals | Only 2 places after dot | 12.345 → 12.34 |
| Add symbol | Put $ at start | 100 → $100 |
Different Currency Formats
US Dollars:
<input x-mask:money="quot; placeholder="$0.00">
<!-- Output: $1,234.56 -->
Euros (comma as decimal):
<input x-mask:money="€" placeholder="€0,00">
<!-- Output: €1.234,56 -->
No Cents:
<input
@input="
let num = $el.value.replace(/\D/g, '');
$el.value = '#x27; + num.replace(
/\B(?=(\d{3})+(?!\d))/g, ','
);
"
>
<!-- Output: $1,234,567 (whole dollars only) -->
Putting It All Together
Here’s a complete form with all three types of masks:
<form x-data="{
phone: '',
card: '',
amount: ''
}">
<!-- Basic Mask: Phone -->
<input
x-mask="(999) 999-9999"
placeholder="Phone Number"
>
<!-- Dynamic Mask: Credit Card -->
<input
x-data="{ mask: '9999 9999 9999 9999' }"
x-mask="mask"
@input="
mask = $el.value.startsWith('3')
? '9999 999999 99999'
: '9999 9999 9999 9999'
"
placeholder="Card Number"
>
<!-- Money Format -->
<input
@input="
let n = $el.value.replace(/[^0-9.]/g,'');
let p = n.split('.');
p[0] = p[0].replace(/\B(?=(\d{3})+(?!\d))/g,',');
if(p[1]) p[1] = p[1].slice(0,2);
$el.value = '#x27; + p.join('.');
"
placeholder="Amount"
>
</form>
Why Input Masks Are Awesome
| Problem | Solution |
|---|---|
| Messy phone numbers | Basic mask keeps format clean |
| Different card types | Dynamic mask adapts automatically |
| Unreadable money amounts | Money formatting adds commas & symbols |
Remember!
- Basic masks = Fixed patterns with
9for numbers andafor letters - Dynamic masks = Patterns that change based on what you type
- Money formatting = Adding commas, decimals, and currency symbols
Input masks make forms easier to use and data cleaner.
They’re like having a friendly helper who says: “Don’t worry, I’ll format that for you!”
🎉 Now you can make text boxes that guide users to type the right way!
