šŸ“ž Formatting Phone Numbers in Angular Made Simple with a Custom Pipe

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.

Leave a Comment

Your email address will not be published. Required fields are marked *