
Displaying clean and readable phone numbers is crucial in any web application. Raw strings of digits just donāt cut it when youāre aiming for a polished user experience. Thatās where Angularās custom pipes come in handy.
In this article, Iāll walk you through a handy PhoneFormatPipe
āa custom Angular pipe I use to format phone numbers into a standard, human-friendly format. It keeps the UI consistent and avoids messy formatting issues, all while staying flexible for different number types.
š What This Pipe Does
The PhoneFormatPipe
takes any raw phone number (as a string or number) and formats it to something more readable, like:
+92 (42) 123-4567
It handles country codes, area codes, hyphenationāand it even avoids reformatting numbers that are already customized by the user.
š§± The Pipe Code
Hereās the full implementation:
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'phoneFormat',
standalone: true,
})
export class PhoneFormatPipe implements PipeTransform {
transform(tel: string | number, usFormat: boolean = true): string {
if (!tel) return '';
const telStr = tel.toString().trim();
// If the input contains more than just digits (or not starting with +), return as-is
if (!/^\+?\d+$/.test(telStr)) {
return telStr;
}
const hasPlus = telStr.indexOf('+') === 0;
const value = telStr.replace(/^\+/, '');
let country: string | number;
let city: string;
let number: string;
switch (value.length) {
case 10:
country = 1;
city = value.slice(0, 3);
number = value.slice(3);
break;
case 11:
country = value[0];
city = value.slice(1, 4);
number = value.slice(4);
break;
case 12:
case 13:
country = value.slice(0, 3);
city = value.slice(3, 5);
number = value.slice(5);
break;
default:
return telStr;
}
number = number.slice(0, 3) + '-' + number.slice(3);
// Hide country code if it's 1 (US-style)
country = country === '1' ? '' : `+${country}`;
return `${country} (${city}) ${number}`.trim();
}
}
š§ How It Works
ā Step 1: Validation
Before formatting, the pipe checks:
- Is the input empty? If yes, return an empty string.
- Does it contain only digits (and an optional
+
at the start)? If not, return the original value untouched. This avoids overriding already formatted or customized values.
āļø Step 2: Strip the +
If the phone number starts with a +
, it gets temporarily removed for slicing. Itās added back in the correct position later.
šŖ Step 3: Slice It Up Based on Length
Hereās how it decides how to format the number:
- 10 digits ā Assumes US format:
+1 (XXX) XXX-XXXX
- 11 digits ā Takes 1-digit country code, 3-digit city code, and the rest as local
- 12/13 digits ā Handles longer international formats with a 3-digit country and 2-digit area code
If the number doesnāt match one of these, itās left untouched.
š§āšØ Step 4: Final Formatting
It inserts a hyphen after the first 3 digits of the local number and rebuilds the final string in this format:
+<country> (<area>) <local-number>
If the country code is 1, itās left out to keep things clean.
š” Why Use a Pipe for This?
Hereās why I use a custom pipe instead of formatting manually in the component:
- Keeps templates clean ā Just use
{{ phone | phoneFormat }}
and youāre done. - Reusable anywhere ā Drop it into forms, contact lists, or detail views.
- Avoids unnecessary logic in components ā Focus your component on behavior, not display formatting.
- Safe for user-entered data ā If a user formats a number their way (e.g., with dashes or spaces), it wonāt get overridden.
ā Example Usage in Template
<span>{{ user.phoneNumber | phoneFormat }}</span>
Want to apply this globally? You can even import this as a standalone pipe and reuse across modules.
š Final Thoughts
The PhoneFormatPipe
is a small but powerful tool to improve UI clarity and keep your Angular app professional and polished. It helps keep your code DRY, your templates clean, and your users happy.
If your app deals with user input or contact data, give this pipe a tryāitās a smart way to standardize phone numbers without cluttering your logic.