npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@fagon/ngx-intl-phone

v1.0.1

Published

A fully-accessible Angular component for international phone number input with real-time validation, formatting, and theming—supporting all countries, multiple layouts (split/group/stack), CSS variable customization, Reactive Forms integration, and detail

Readme

IntlPhoneNumber

Angular TypeScript License Reactive Forms Standalone Components PRs Welcome Made with Love


Overview

NgxIntlPhone is a robust, highly-configurable Angular component for international phone number input, validation, and formatting. It supports all countries, integrates seamlessly with Angular Reactive Forms, and provides three beautiful layouts in a single, easy-to-use API.

  • 📱 All-in-one: Country selection, phone validation, formatting, and error display
  • 🌍 Global: Supports every country and dial code
  • 🎨 Flexible: Three layouts (split, group, stack) for any UI
  • 🧩 Angular-native: Works with standalone components and NgModules
  • 🧪 Reactive Forms: Implements ControlValueAccessor for form integration
  • 🛡️ Accessible: Keyboard navigation, ARIA attributes, and focus management
  • 🎛️ Customizable: Theming via CSS variables, configurable labels, and more

Installation

npm install @fagon/ngx-intl-phone

Peer Dependencies

  • @angular/core, @angular/common, @angular/forms (v16+)
  • libphonenumber-js (for validation/formatting)
  • i18n-iso-countries (for country names)

Quick Start

1. Import the Module

import { IntlPhoneModule } from "@fagon/ngx-intl-phone";

@NgModule({
  imports: [IntlPhoneModule]
})
export class AppModule {}

Or, for standalone components:

import { IntlPhoneComponent } from "@fagon/ngx-intl-phone";

2. Basic Usage

<intl-phone [(ngModel)]="phone"></intl-phone>
<!-- or with Reactive Forms -->
<intl-phone [formControl]="phoneControl"></intl-phone>

3. Import Styles

The component ships with encapsulated styles that work out of the box in most setups. However, if your application enforces a strict Content Security Policy (CSP) — particularly one that blocks inline styles (style-src 'unsafe-inline') — the component's encapsulated styles may be suppressed by the browser.

In that case, import the pre-built stylesheet globally instead:

In angular.json:

"styles": [
  "node_modules/@fagon/ngx-intl-phone/styles.css",
  "src/styles.css"
]

Or in your global stylesheet (src/styles.scss / src/styles.css):

@import "@fagon/ngx-intl-phone/styles.css";

When to use this: Enable this import if you see the component rendering without borders, layout, or dropdown styling under a strict CSP. It is also recommended for Angular Universal (SSR) projects, where component-encapsulated styles may not be applied during server-side rendering.


Layouts

Switch between three layouts using the layout input:

  • split (default): Country selector and input side-by-side
  • group: Unified input with divider
  • stack: Vertically stacked fields with labels
<!-- Split (default) -->
<intl-phone></intl-phone>
<intl-phone layout="split"></intl-phone>

<!-- Group -->
<intl-phone layout="group"></intl-phone>

<!-- Stack (labels required) -->
<intl-phone
  layout="stack"
  countryLabel="Country"
  phoneLabel="Phone Number"
></intl-phone>

Inputs

| Input | Type | Default | Description | | ------------------ | ------------------------------- | ---------------------- | ------------------------------------------------------------------------------------ | | layout | 'split' \| 'group' \| 'stack' | 'split' | Layout style for the input | | countryLabel | string | 'Country' | Label for country selector (required for stack layout) | | phoneLabel | string | 'Phone Number' | Label for phone input (required for stack layout) | | placeholder | string | 'Enter phone number' | Input placeholder | | defaultCountry | string (ISO2 or name) | 'GH' | Default selected country (ISO2 code or full name, e.g. 'GH' or 'Ghana') | | allowedCountries | string[] (ISO2 codes) | undefined | Restrict selectable countries (e.g. ["GH", "NG", "KE"]). All countries if omitted. | | config | IntlPhoneConfig | See below | Theming and behavior overrides |


Available Countries

By default, all countries are available. To restrict the dropdown, use allowedCountries:

<intl-phone [allowedCountries]="['GH', 'NG', 'KE', 'ZA']"></intl-phone>

Default Country

Set the default country by ISO2 code or full name:

<intl-phone defaultCountry="NG"></intl-phone>
<intl-phone defaultCountry="Nigeria"></intl-phone>

If the value is not found, the first country in the list is used.


Practical Examples

Restrict to West Africa

<intl-phone
  [allowedCountries]="['GH', 'NG', 'CI', 'SN', 'GM']"
  defaultCountry="GH"
  [(ngModel)]="phone"
></intl-phone>

Custom Labels and Placeholder

<intl-phone
  layout="stack"
  countryLabel="Select Country"
  phoneLabel="Mobile Number"
  placeholder="e.g. 024 123 4567"
  [(ngModel)]="phone"
></intl-phone>

Reactive Forms with Allowed Countries

form = new FormGroup({
  phone: new FormControl("", Validators.required)
});
<form [formGroup]="form">
  <intl-phone
    formControlName="phone"
    [allowedCountries]="['GH', 'NG', 'KE']"
    defaultCountry="KE"
  ></intl-phone>
</form>

Outputs

| Output | Type | Description | | ------------- | ----------------------- | --------------------------------------- | | validChange | EventEmitter<boolean> | Emits validity state when phone changes |


Types

IntlPhoneConfig

export interface IntlPhoneConfig {
  borderColor?: string;
  borderColorHover?: string;
  borderColorFocus?: string;
  borderColorInvalid?: string;
  borderColorValid?: string;
  borderRadius?: string;
  inputHeight?: string;
  dropdownMaxHeight?: string;
  fontSize?: string;
  fontFamily?: string;
}

Default Config

export const DEFAULT_INTL_PHONE_CONFIG: Required<IntlPhoneConfig> = {
  borderColor: "#e9ecef",
  borderColorHover: "#b5afa8",
  borderColorFocus: "#e9ecef",
  borderColorInvalid: "#e90b0b",
  borderColorValid: "#198754",
  borderRadius: "12px",
  inputHeight: "44px",
  dropdownMaxHeight: "264px",
  fontSize: "14px",
  fontFamily: "inherit"
};

Country

export interface Country {
  name: string;
  iso2: string;
  dialCode: string;
  flag: string;
}

Works with both template-driven and reactive forms:

form = new FormGroup({
  phone: new FormControl("", Validators.required)
});
<form [formGroup]="form">
  <intl-phone formControlName="phone"></intl-phone>
</form>

Theming & Customization

Override any CSS variable to match your design system:

intl-phone {
  --phone-height: 48px;
  --phone-border: #e0e0e0;
  --phone-border-focus: #1976d2;
  --phone-border-invalid: #d32f2f;
  --phone-border-valid: "#198754";
  --phone-radius: 8px;
  --phone-font-size: 16px;
  --phone-font-family: "Inter", sans-serif;
}

Note: CSS variable overrides apply regardless of whether you are using component-encapsulated styles or the global styles.css import. See Import Styles for guidance on which approach suits your setup.


Advanced Configuration

You can provide a global config using the module:

IntlPhoneModule.forRoot({
  borderRadius: "8px",
  borderColorFocus: "#1976d2",
  inputHeight: "48px"
});

Or per-component:

<intl-phone
  [config]="{ borderColor: '#333', inputHeight: '40px' }"
></intl-phone>

Accessibility

  • Full keyboard navigation
  • ARIA attributes for dropdown and input
  • Focus ring and invalid state styling

Example

<intl-phone
  layout="group"
  [placeholder]="'Your mobile number'"
  [defaultCountryName]="'Nigeria'"
  [config]="{
    borderColor: '#bdbdbd',
    borderColorFocus: '#1976d2',
    borderRadius: '6px'
  }"
  (validChange)="onPhoneValid($event)"
  [(ngModel)]="phone"
></intl-phone>

License

MIT © Fagon Technologies


Contributing

PRs welcome! Please open an issue to discuss your proposal before submitting.


Support

For questions, issues, or feature requests, please open an issue on GitHub.


Enjoy building with IntlPhoneNumber!