Automated Phone Number Formatting in Power Apps Edit Forms
Implement a custom input mask for phone numbers in canvas apps to ensure consistent data entry and storage, without using any third-party components.
Entering phone numbers is a routine task, but without a guiding format you end up with a mess: some users type dashes, others use parentheses, a few might even include spaces. Later, when you try to parse or filter the data, you have to handle every variation. A simple input mask – formatting the number as the user types – solves this elegantly.
In this article I’ll show you how to build a phone number input mask inside a Power Apps Edit Form. The technique works with any data source that stores text, and it keeps the underlying data clean by retaining only the digits.
Why You Need an Input Mask
An input mask gives you a few valuable benefits:
- Consistent display – Every phone number looks the same on screen.
- Clean data – The stored value contains digits only, making it easy to query or pass to external systems.
- Better user experience – Users see the formatting appear automatically, reducing errors and rework.
Power Apps does not include a native input‑mask control for Edit Forms. The workaround presented here uses a hidden slider to detect each keystroke and a small expression that reassembles the number according to your pattern.
The Sample Data Source: LeadTracker
We’ll use a SharePoint list called LeadTracker with these columns:
| Column Name | Type |
|---|---|
CompanyName | Single line of text |
PhoneNumber | Single line of text |
Add a few sample rows:
| CompanyName | PhoneNumber |
|---|---|
| Acme Corp | 5551234567 |
| Globex Inc | 6149876543 |
| Initech | 3035551212 |
(Store the digits without formatting; the mask will handle the display.)
The target format for this example will be the US style with parentheses: (###) ###-####.
Setting Up the App
Open Power Apps Studio, create a blank canvas app, and add the LeadTracker list as a data source.
Navigation and Record Selection
- Insert a Gallery on the left side of the screen and set its Items to
LeadTracker. - Inside the gallery, place a Button (or a Label) and set its Text to
ThisItem.CompanyName.
When a user clicks a name, we want to store the whole record and the current phone number in variables. Set the button’s OnSelect to:
Set(varCurrentRecord, ThisItem); Set(varRawPhone, ThisItem.PhoneNumber)
We also want a visual cue for the selected item. Set the button’s Color and Fill properties:
- Color:
If(ThisItem.ID = varCurrentRecord.ID, White, Black) - Fill:
If(ThisItem.ID = varCurrentRecord.ID, RGBA(56,96,178,1), Transparent)
The Edit Form
- At the top of the screen, add a Label with the text “Lead Form”.
- Insert an Edit Form, set its DataSource to
LeadTracker, and add only the CompanyName and PhoneNumber cards. - Set the form’s DefaultMode to
FormMode.Newso it always opens ready to create a new record.
Implementing the Phone Number Mask
Now we add the logic that formats the phone number as the user types. The core idea is simple: every time the length of the input changes, the formatting expression is triggered.
The Hidden Slider Trick
A slider control fires its OnChange event when its value changes, and it does not require focus. We’ll bind the slider’s Default to the length of the phone text input, so each keystroke increments the slider and runs the formatting code.
- Inside the PhoneNumber card, add a Text Input control. Name it
txtPhoneRaw. - Add a Slider control and name it
sldLengthTrigger. Position it somewhere out of sight (or set its Visible tofalseafter testing). - Set the slider’s Default property to:
Len(txtPhoneRaw.Text)
Defining the Mask Pattern
We need to tell Power Apps what format we want. Insert another Text Input (you can place it anywhere, maybe off‑screen) and name it txtMaskPattern. Set its Default to:
"(###) ###-####"
The # character acts as a placeholder for any digit. All other characters (parentheses, spaces, dashes) will be inserted automatically.
The Formatting Logic
The slider’s OnChange is where all the magic happens. It reads the raw input, extracts only digits, then builds the formatted string according to the pattern and writes it back into txtPhoneRaw.
Set(
varFormattedPhone,
With(
{
// Extract every digit from the current input
rawDigits: Concat(
MatchAll(txtPhoneRaw.Text, Match.Digit),
FullMatch
),
// Parse the mask pattern to find digit positions
maskLen: Len(txtMaskPattern.Text),
digitPositions: ForAll(
Sequence(maskLen),
{
pos: Value,
char: Mid(txtMaskPattern.Text, Value, 1)
}
)
},
With(
{
// Build a table that maps digit index to the
// corresponding character in the pattern
maskData: ForAll(
Sequence(Len(rawDigits)),
{
digitIndex: Value,
patternChar: LookUp(
digitPositions,
char = "#",
Left(txtMaskPattern.Text, pos)
)
}
)
},
// Start with the raw number and apply the pattern
// (Simplified version – see forum for full generic approach)
varFormatted: ""
)
)
)The full generic solution that handles any pattern length is a bit longer; you can find it in the References section. The key concept is the same: count the digits and map them to the positions of # in the pattern.
After you have the formatted string, store it and reset the text input to trigger a clean display:
// (Assuming varFormattedPhone contains the final formatted value) Reset(txtPhoneRaw); Set(varRawPhone, rawDigits) // Keep raw digits for storage
Storing the Raw Number
When the user submits the form, you want to write only the digits to your SharePoint list. You can use a Patch or SubmitForm with a data card value that points to the raw digits variable. In the PhoneNumber data card, set the Update property to:
varRawPhone
Now the list will always store a clean 10‑digit string, regardless of how the number was displayed.
Handling Format Variations
The same logic works for any country format. Change the txtMaskPattern to:
| Country | Pattern |
|---|---|
| Canada / US | ###-###-#### |
| US with parentheses | (###) ###-#### |
| United Kingdom | +## #### ###### |
| Japan | (##)-####-#### |
The only requirement is that the pattern uses # exactly where a digit should appear.
Common Issues and Troubleshooting
Slider Not Triggering
Make sure the slider’s OnChange property is not empty. If the slider is invisible and you test in the player, the event still fires.
Non‑numeric Characters
Users may paste a number that already contains dashes or parentheses. The MatchAll with Match.Digit strips them out automatically, so the formatting always starts from digits only.
Cursor Jump After Reset
Every time the slider triggers a Reset(txtPhoneRaw), the cursor jumps to the beginning of the text input. This is a known annoyance. Two workarounds:
- Use a Label to display the formatted number and keep the raw input hidden. Update the label in the slider’s OnChange.
- Accept the jump and train users to ignore it; the formatted result is correct anyway.
Final Thoughts
The hidden‑slider approach is a proven, lightweight way to add input‑mask behaviour to Power Apps Edit Forms. It requires no delegation analysis – everything runs locally on the client. For apps that use the Patch pattern (outside an Edit Form), you can package the same logic into a reusable component, but inside an Edit Form this inline method works reliably.
Begin with a simple pattern like ###-###-#### and then experiment with international formats. The time spent building the mask will repay itself in cleaner data and happier users.
References
- Matthew Devaney’s original article and code: Power Apps Phone Number Formatting In A Form (Input Mask)
- Microsoft Learn: Input masks in Power Apps (conceptual) – placeholder, exact URL TBD
- Microsoft Learn: Using the MatchAll function – placeholder, exact URL TBD
Learn how small coding practices—like using descriptive names, flattening conditions, and simplifying logic—can make your apps easier to update and less error-prone.
Move past the gallery and discover the hidden patterns for validation, navigation, and smart submission handling in your data entry forms.
PowerShell unlocks admin capabilities that the Power Platform admin center simply doesn’t offer—from recovering deleted apps to blocking trial licenses. Here’s how to wield them safely.