Tutorials/Power Apps/Automated Phone Number Formatting in Power Apps Edit Forms
Power Appsintermediate

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.

NA
Narmer Abader
@narmer · Published June 3, 2026

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 NameType
CompanyNameSingle line of text
PhoneNumberSingle line of text

Add a few sample rows:

CompanyNamePhoneNumber
Acme Corp5551234567
Globex Inc6149876543
Initech3035551212

(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.

  1. Insert a Gallery on the left side of the screen and set its Items to LeadTracker.
  2. 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:

powerfxOnSelect of the gallery button
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

  1. At the top of the screen, add a Label with the text “Lead Form”.
  2. Insert an Edit Form, set its DataSource to LeadTracker, and add only the CompanyName and PhoneNumber cards.
  3. Set the form’s DefaultMode to FormMode.New so 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.

  1. Inside the PhoneNumber card, add a Text Input control. Name it txtPhoneRaw.
  2. Add a Slider control and name it sldLengthTrigger. Position it somewhere out of sight (or set its Visible to false after testing).
  3. Set the slider’s Default property to:
powerfxSlider Default
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:

powerfxMask pattern
"(###) ###-####"

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.

powerfxSlider OnChange – full expression
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:

powerfxContinued OnChange
// (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:

powerfxPhoneNumber card Update
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:

CountryPattern
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