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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@afd-software/pce-angular

v20.0.0

Published

Angular module that allows for easy integration of AFD Software's powerful PCE address lookup and form validation engine.

Downloads

449

Readme

Angular Integration Manual

Contents


Introduction

The Angular module for AFD Postcode Evolution® (PCE) allows developers to easily harness the power of PCE in front-end Angular applications.

When filling out address forms, users simply need to start typing their address in a single TypeAhead box that will drill down on the results until the user can select their address from the list.

The plugin also has powerful validation tools that allow validation of phone numbers, email addresses, credit/debit cards, and UK bank accounts. In addition to validation it is possible to extract further information from the fields (for example "card type"), restrict input to certain keys and format the fields automatically, independent of the actual keys pressed by the user.


Compatibility

This module is compatible with Angular 19.0.0 and above. All directives and components are now standalone, making them easier to use in modern Angular applications without the need for NgModules.

Key Changes from Previous Versions

  • All directives and components are now standalone
  • The AfdPceAngularModule is deprecated – import standalone directives directly instead
  • Uses Angular's signals for reactive state management
  • Requires @angular/cdk for overlay positioning

Migration Guide

This section covers migrating from previous versions of @afd-software/pce-angular (v18 and earlier) to v19+.

Step 1: Update the Package

npm install @afd-software/pce-angular@latest

You will also need to install @angular/cdk if you haven't already:

npm install @angular/cdk

Step 2: Remove Module Imports

Before (v18 and earlier):

// app.module.ts
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { AfdPceAngularModule } from '@afd-software/pce-angular';

@NgModule({
  imports: [
    HttpClientModule,
    AfdPceAngularModule
  ]
})
export class AppModule { }

After (v19+):

The module is no longer needed. Instead, import standalone directives directly into your components:

// app.component.ts
import { Component } from '@angular/core';
import { 
  AfdTypeaheadFormDirective,
  AfdTypeaheadDirective,
  AfdAddressFieldInputDirective
} from '@afd-software/pce-angular';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [
    AfdTypeaheadFormDirective,
    AfdTypeaheadDirective,
    AfdAddressFieldInputDirective
  ],
  templateUrl: './app.component.html'
})
export class AppComponent { }

Step 3: Update HTTP Client Configuration

Before (v18 and earlier):

import { HttpClientModule } from '@angular/common/http';

@NgModule({
  imports: [HttpClientModule]
})

After (v19+):

Use provideHttpClient() in your application config:

// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideHttpClient } from '@angular/common/http';

export const appConfig: ApplicationConfig = {
  providers: [
    provideHttpClient()
  ]
};

Step 4: Update Address Field Directives

Before (v18 and earlier):

<input type="text" [afdResult]="'Property'">
<input type="text" [afdResult]="'Street'">
<input type="text" [afdResult]="'Town'">
<input type="text" [afdResult]="'Postcode'">

After (v19+):

Use the new afdAddressFieldInput directive:

<input type="text" afdAddressFieldInput="Property">
<input type="text" afdAddressFieldInput="Street">
<input type="text" afdAddressFieldInput="Town">
<input type="text" afdAddressFieldInput="Postcode">

Step 5: Update TypeAhead Form Setup

Before (v18 and earlier):

<div afdTypeahead [options]="afdOptions">
  <input type="text" afdTypeaheadInput>
</div>

After (v19+):

<div [afdTypeaheadForm]="afdOptions">
  <input type="text" afdTypeahead>
</div>

Step 6: Update Validation Directives

Validation directives remain largely the same but are now standalone:

// Before: imported via module
import { AfdPceAngularModule } from '@afd-software/pce-angular';

// After: import directly
import { 
  AfdEmailRegexValidDirective,
  AfdEmailPceValidDirective,
  AfdPhoneRegexValidDirective,
  AfdPhonePceValidDirective,
  AfdCardRegexValidDirective,
  AfdExpiryRegexValidDirective,
  AfdCardPceValidDirective,
  AfdAccountRegexValidDirective,
  AfdSortRegexValidDirective,
  AfdAccountPceValidDirective
} from '@afd-software/pce-angular';

Breaking Changes Summary

| Change | Impact | |----------------------------------|--------| | Standalone directives | Must import directives individually in component imports array | | AfdPceAngularModule deprecated | Remove from NgModule imports | | HttpClientModule deprecated | Use provideHttpClient() in app config | | afdResult deprecated | Replace with afdAddressFieldInput | | Signals-based reactivity | Address fields update automatically via Angular signals | | @angular/cdk required | Must be installed as a peer dependency |

Standalone Component Setup

Import the standalone directives and components directly into your component:

// app.component.ts
import { Component, OnInit } from '@angular/core';
import { provideHttpClient } from '@angular/common/http';
import { 
  AFDTypeaheadService,
  AfdTypeaheadFormDirective,
  AfdTypeaheadDirective,
  AfdResultDirective 
} from '@afd-software/pce-angular';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [
    AfdTypeaheadFormDirective,
    AfdTypeaheadDirective,
    AfdResultDirective
  ],
  templateUrl: './app.component.html'
})
export class AppComponent implements OnInit {
  afdOptions = {
    id: 'YOUR_ID',
    token: 'YOUR_TOKEN',
    pceURL: 'https://apps.afd.co.uk/json'
  };

  ngOnInit() {}
}

Application Configuration

In your app.config.ts, ensure you provide the HTTP client:

// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideHttpClient } from '@angular/common/http';

export const appConfig: ApplicationConfig = {
  providers: [
    provideHttpClient()
  ]
};

Legacy Module Setup (Deprecated)

If you're migrating from an older version, the module import still works but is deprecated:

// app.module.ts (DEPRECATED)
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { FormsModule } from '@angular/forms';
import { AfdPceAngularModule } from '@afd-software/pce-angular';

@NgModule({
  imports: [
    HttpClientModule,
    FormsModule,
    AfdPceAngularModule  // Deprecated - use standalone imports instead
  ]
})
export class AppModule { }

Authentication

The AFD API accepts two types of credential pairs Serial/Password and ID/Token, each with its own pceURL. Typically, ID/Token is recommended.

ID/Token (Recommended for Production)

afdOptions = {
  id: 'YOUR_ID',
  token: 'YOUR_TOKEN',
  pceURL: 'https://apps.afd.co.uk/json'
};

Serial/Password (Development Only)

IMPORTANT: Serial/Password credentials are not for use in public-facing websites. For more information, contact the AFD Support team.

afdOptions = {
  serial: 'YOUR_SERIAL',
  password: 'YOUR_PASSWORD',
  pceURL: 'https://pce.afd.co.uk/afddata.pce'
};

That's it, now you are ready to start adding controls to forms.


Address Lookup

"TypeAhead" functionality allows users to search for addresses and see results in real-time as they type. Our Angular TypeAhead controls make adding type ahead to an Angular project simple.

TypeAhead Control

To set up TypeAhead, use the afdTypeaheadForm directive on a container element and the afdTypeahead directive on an input.

Important: The afdTypeahead input and all afdAddressFieldInput result fields must be placed inside the same afdTypeaheadForm container. The form directive provides the shared service that connects the typeahead search to the result fields.

<!-- app.component.html -->
<div [afdTypeaheadForm]="afdOptions">
  <div class="form-control">
    <label for="afd-typeahead">Search Address</label>
    <input 
      id="afd-typeahead" 
      type="text" 
      afdTypeahead 
      placeholder="Start typing your address..."
    >
  </div>
  
  <!-- Result fields - automatically populated when an address is selected -->
  <div class="form-control">
    <label>Property</label>
    <input type="text" afdAddressFieldInput="Property">
  </div>
  <div class="form-control">
    <label>Street</label>
    <input type="text" afdAddressFieldInput="Street">
  </div>
  <div class="form-control">
    <label>Town</label>
    <input type="text" afdAddressFieldInput="Town">
  </div>
  <div class="form-control">
    <label>Postcode</label>
    <input type="text" afdAddressFieldInput="Postcode">
  </div>
</div>
// app.component.ts
import { Component } from '@angular/core';
import { 
  AfdTypeaheadFormDirective,
  AfdTypeaheadDirective,
  AfdAddressFieldInputDirective,
  AFDTypeaheadOptions
} from '@afd-software/pce-angular';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [
    AfdTypeaheadFormDirective,
    AfdTypeaheadDirective,
    AfdAddressFieldInputDirective
  ],
  templateUrl: './app.component.html'
})
export class AppComponent {
  afdOptions: AFDTypeaheadOptions = {
    id: 'YOUR_ID',
    token: 'YOUR_TOKEN',
    pceURL: 'https://apps.afd.co.uk/json',
    maxQuantity: 5,
    minLength: 3
  };
}

That's it, now when you start typing an address in the box you will be presented with results (5 by default).

International Searches

There are two ways to specify a country for international searches: static country selection and dynamic country selection.

Static Country Selection

This method is for situations in which there will only ever be one country set for searches. To specify the country, add the country input to the afdTypeaheadForm directive:

<div [afdTypeaheadForm]="afdOptions" country="USA">
  <input type="text" afdTypeahead>
  <!-- result fields -->
</div>

Dynamic Country Selection

This method allows users to update the country dynamically. Use the afdCountries directive to populate a select element with available countries, and access the countries list via the afdTypeaheadForm directive's countries property:

<div [afdTypeaheadForm]="afdOptions" [country]="selectedCountry" #typeaheadForm="afdTypeaheadForm">
  <select afdCountries="GBR" [(ngModel)]="selectedCountry">
    <option *ngFor="let country of typeaheadForm.countries" [value]="country.iso">
      {{ country.name }}
    </option>
  </select>
  
  <input type="text" afdTypeahead>
  <!-- result fields -->
</div>
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { 
  AfdTypeaheadFormDirective,
  AfdTypeaheadDirective,
  AfdCountriesDirective
} from '@afd-software/pce-angular';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [
    FormsModule,
    AfdTypeaheadFormDirective,
    AfdTypeaheadDirective,
    AfdCountriesDirective
  ]
})
export class AppComponent {
  selectedCountry = 'GBR';
}

Key points:

  • #typeaheadForm="afdTypeaheadForm" - Export the directive as a template reference variable to access its properties.
  • typeaheadForm.countries - Access the countries list directly from the directive in the template.
  • afdCountries - This directive triggers a query against PCE to get a list of the available countries.
  • ="GBR" - Optionally a country can be set as a default country in the select list. Only ISO3 country codes are accepted.

Results Controls

Once the user selects a result from the TypeAhead control, the module will query PCE to retrieve the full result for the selected address and automatically populate the result fields.

For setting results, use the afdAddressFieldInput directive on input controls. This directive reactively updates when an address is selected and also implements ControlValueAccessor for seamless Angular forms integration.

Note: All afdAddressFieldInput fields must be inside the same afdTypeaheadForm container as the afdTypeahead input.

<input type="text" afdAddressFieldInput="Property">
<input type="text" afdAddressFieldInput="Street">
<input type="text" afdAddressFieldInput="Locality">
<input type="text" afdAddressFieldInput="Town">
<input type="text" afdAddressFieldInput="County">
<input type="text" afdAddressFieldInput="Postcode">

All PCE fields are accessible and are assigned using the afdAddressFieldInput directive. A full list of result fields can be found in the PCE JSON manual.

Reverse Geocoding

The afdReverseGeocode directive allows users to find addresses near their current location using the browser's geolocation API:

<button afdReverseGeocode>Find My Location</button>
import { Component, HostListener } from '@angular/core';
import { AfdReverseGeocodeDirective } from '@afd-software/pce-angular';

@Component({
  standalone: true,
  imports: [AfdReverseGeocodeDirective]
})
export class AppComponent {
  @HostListener('document:afdReverseGeocodeComplete', ['$event'])
  onReverseGeocodeComplete(e: any) {
    console.log('Nearby addresses:', e.detail);
  }
}

Events

There is a single event, afdRetrieveComplete, that is fired on the document when a retrieve has been completed. This is a good way to look at the available fields or add some extra logic once the retrieve task has been completed.

import { Component, HostListener } from '@angular/core';

@Component({...})
export class AppComponent {
  @HostListener('document:afdRetrieveComplete', ['$event'])
  onAfdRetrieveComplete(e: any) {
    console.log('Retrieved address:', e.detail.body['Item'][0]);
  }
}

Styling

The results list component uses CSS custom properties (variables) for easy customization. You can override these variables in your global styles or component styles.

CSS Custom Properties

/* Override CSS variables for the results list */
:root {
  /* Results list container */
  --afd-results-list-background-color: #fcfcfc;
  --afd-results-list-border-color: #ccc;
  --afd-results-list-min-width: 400px;
  --afd-results-list-max-height: auto;
  
  /* Results list items */
  --afd-results-list-item-padding: 4px 4px 8px 8px;
  
  /* Highlighted item (keyboard navigation / hover) */
  --afd-results-list-item-highlighted-background-color: #2272b9;
  --afd-results-list-item-highlighted-color: #fff;
  
  /* Font settings */
  --afd-results-font-family: sans-serif;
  --afd-results-color: #333;
}

CSS Classes

You can also target the following CSS classes directly:

/* Style the results list container */
.afd-results-list {
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  border-radius: 4px;
}

/* Style individual result items */
.afd-results-list-item {
  padding: 8px 12px;
  cursor: pointer;
}

/* Highlighted item (keyboard navigation) */
.afd-results-list-item-highlighted {
  background-color: #2272b9;
  color: #fff;
}

Style Options

You can also pass style objects through the options:

afdOptions: AFDTypeaheadOptions = {
  id: 'YOUR_ID',
  token: 'YOUR_TOKEN',
  resultsListStyle: { width: '400px' },
  resultsItemStyle: { padding: '10px' },
  matchPositionsStyle: { fontWeight: 'bold', color: '#007bff' }
};

TypeAhead Options

The AFDTypeaheadOptions type provides many configuration options:

| Option | Type | Default | Description | |--------|------|---------|------------------------------------------------------------| | id | string | - | AFD ID credential | | token | string | - | AFD Token credential | | pceURL | string | https://apps.afd.co.uk/json | PCE service URL | | maxQuantity | number | 5 | Maximum lookup results to display | | minLength | number | 3 | Minimum in search characters before searching | | afterHideTypeahead | boolean | true | Hide typeahead after address selection | | searchAgainButton | boolean | true | Show "search again" button | | beforeHideResults | boolean | true | Hide result fields before search | | manualInputButton | boolean | true | Show manual input button | | matchPositions | boolean | false | Highlight matched text | | postcodeFirst | boolean | true | Show postcode before/after address | | hideEmpties | boolean | false | Hide empty result fields | | pushUp | string[] | null | Fields to push up when empty | | retrieveFields | string | 'standard' | Field format: standard, international, usa, bs7666 |


Credit Card Validation

Card validation happens via three attribute directives. The first two check that the structure of the card number and the expiry date are correct. If both of these checks return valid then a validation directive placed on the parent form will fire and validate the pair of values against PCE. In addition to validation it is also possible to extract information about the card.

Card Validation

As each call to PCE is charged for we do not want to send validation requests for numbers that are clearly not valid. As such, we first try to validate the card number and expiry date via a regular expression check and only when the patterns are valid do we request validation from PCE.

For this first stage we have two attribute directives afdCardRegexValid and afdExpiryRegexValid, these should each be placed on the relevant input.

Once both of these controls are valid we then want to query PCE to validate the combination. To do this we place the afdCardPceValid directive on the parent form.

Important: It is essential that you include both of these base directives in the controls. If you only use afdCardPceValid you will request validation from PCE on each keystroke which will raise excessive charges.

<form #cardForm="ngForm" afdCardPceValid>
  <div class="form-field">
    <label>Card Number</label>
    <input 
      name="cardControl" 
      type="text" 
      afdCardRegexValid
      [(ngModel)]="card"
      #cardControl="ngModel"
    >
    <span class="error" *ngIf="cardControl.hasError('afdCardRegexValid') && cardControl.touched">
      {{ cardControl.errors!['afdCardRegexValid'].message }}
    </span>
  </div>
  
  <div class="form-field">
    <label>Expiry Date</label>
    <input 
      name="expiryControl" 
      type="text" 
      afdExpiryRegexValid
      [(ngModel)]="expiry"
      #expiryControl="ngModel"
    >
    <span class="error" *ngIf="expiryControl.hasError('afdExpiryRegexValid') && expiryControl.touched">
      {{ expiryControl.errors!['afdExpiryRegexValid'].message }}
    </span>
  </div>
  
  <span class="error" *ngIf="cardForm.hasError('afdCardPceValid')">
    {{ cardForm.errors!['afdCardPceValid'].message }}
  </span>
</form>
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { 
  AfdCardRegexValidDirective,
  AfdExpiryRegexValidDirective,
  AfdCardPceValidDirective,
  AFDCardService
} from '@afd-software/pce-angular';

@Component({
  standalone: true,
  imports: [
    FormsModule,
    AfdCardRegexValidDirective,
    AfdExpiryRegexValidDirective,
    AfdCardPceValidDirective
  ]
})
export class CardComponent {
  card = '';
  expiry = '';
  
  constructor(private afdCardService: AFDCardService) {
    // Set your credentials
    this.afdCardService.options = {
      id: 'YOUR_ID',
      token: 'YOUR_TOKEN'
    };
  }
}

Card Additional Information

It is possible to know some things about a card even before its number has been input in its entirety. We allow access to this via an Observable on the AFDCardService.

import { Component, OnInit, OnDestroy } from '@angular/core';
import { AFDCardService } from '@afd-software/pce-angular';
import { Subscription } from 'rxjs';

@Component({...})
export class CardComponent implements OnInit, OnDestroy {
  cardInfoSubscription: Subscription;
  cardInfo: any;
  
  constructor(private afdCardService: AFDCardService) {}
  
  ngOnInit() {
    this.cardInfoSubscription = this.afdCardService.cardInfo.subscribe(data => {
      this.cardInfo = data;
    });
  }
  
  ngOnDestroy() {
    this.cardInfoSubscription?.unsubscribe();
  }
}

The full cardInfo object:

cardInfo: {
  pceValid: boolean;        // PCE validation result
  cardRegexValid: boolean;  // Card number format valid
  expiryRegexValid: boolean; // Expiry date format valid
  cardTypeNice: string;     // Human-readable card type (e.g., "Visa")
  cardType: string;         // Card type code
  cardNumber: string;       // The card number
  expiryDate: string;       // The expiry date
}

Bank Account Validation

Bank Account validation happens via three attribute directives. The first two check that the structure of the account number and the sort code are correct. If both of these checks return valid then a validation directive placed on the parent form will fire and validate the pair of values against PCE. In addition to validation it is also possible to extract information about the bank account.

Account Validation

As each call to PCE is charged for we do not want to send validation requests for numbers that are clearly not valid. As such, we first try to validate the account number and sort code via a regular expression check and only when the patterns are valid do we request validation from PCE.

For this first stage we have two attribute directives afdAccountRegexValid and afdSortRegexValid, these should each be placed on the relevant input.

Once both of these controls are valid we then want to query PCE to validate the combination. To do this we place the afdAccountPceValid directive on the parent form.

Important: It is essential that you include both of these base directives in the controls. If you only use afdAccountPceValid you will request validation from PCE on each keystroke which will raise excessive charges.

<form #accountForm="ngForm" afdAccountPceValid>
  <div class="form-field">
    <label>Account Number</label>
    <input 
      name="accountControl" 
      type="text" 
      afdAccountRegexValid
      [(ngModel)]="account"
      #accountControl="ngModel"
    >
    <span class="error" *ngIf="accountControl.hasError('afdAccountRegexValid') && accountControl.touched">
      {{ accountControl.errors!['afdAccountRegexValid'].message }}
    </span>
  </div>
  
  <div class="form-field">
    <label>Sort Code</label>
    <input 
      name="sortControl" 
      type="text" 
      afdSortRegexValid
      [(ngModel)]="sort"
      #sortControl="ngModel"
    >
    <span class="error" *ngIf="sortControl.hasError('afdSortRegexValid') && sortControl.touched">
      {{ sortControl.errors!['afdSortRegexValid'].message }}
    </span>
  </div>
  
  <span class="error" *ngIf="accountForm.hasError('afdAccountPceValid') && accountForm.touched">
    {{ accountForm.errors!['afdAccountPceValid'].message }}
  </span>
</form>
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { 
  AfdAccountRegexValidDirective,
  AfdSortRegexValidDirective,
  AfdAccountPceValidDirective,
  AFDAccountService
} from '@afd-software/pce-angular';

@Component({
  standalone: true,
  imports: [
    FormsModule,
    AfdAccountRegexValidDirective,
    AfdSortRegexValidDirective,
    AfdAccountPceValidDirective
  ]
})
export class AccountComponent {
  account = '';
  sort = '';
  
  constructor(private afdAccountService: AFDAccountService) {
    this.afdAccountService.options = {
      id: 'YOUR_ID',
      token: 'YOUR_TOKEN'
    };
  }
}

Account Additional Information

It is possible to know some things about an account even before its number has been input in its entirety. We allow access to this via an Observable on the AFDAccountService.

import { Component, OnInit, OnDestroy } from '@angular/core';
import { AFDAccountService } from '@afd-software/pce-angular';
import { Subscription } from 'rxjs';

@Component({...})
export class AccountComponent implements OnInit, OnDestroy {
  accountInfoSubscription: Subscription;
  accountInfo: any;
  
  constructor(private afdAccountService: AFDAccountService) {}
  
  ngOnInit() {
    this.accountInfoSubscription = this.afdAccountService.accountInfo.subscribe(data => {
      this.accountInfo = data;
    });
  }
  
  ngOnDestroy() {
    this.accountInfoSubscription?.unsubscribe();
  }
}

The full accountInfo object:

accountInfo: {
  pceValid: boolean;         // PCE validation result
  accountRegexValid: boolean; // Account number format valid
  sortRegexValid: boolean;    // Sort code format valid
  iban: string;              // IBAN number
  clearingSystem: string;    // Clearing system
  rollNumber: string;        // Roll number (building societies)
  accountType: string;       // Type of account
  accountNumber: string;     // The account number
  sortCode: string;          // The sort code
}

Phone Number Validation

Phone validation happens via two attribute directives that are added to an input control. The directives integrate with the intl-tel-input library to provide international phone number formatting and validation. In addition to validation it is also possible to extract information about the phone number.

Phone Validation

As each call to PCE is charged for we do not want to send validation requests for numbers that are clearly not valid. As such, we first try to validate the phone number via syntax checking and only when the pattern is valid do we request validation from PCE.

For this we have two attribute directives afdPhoneSyntaxValid (or afdPhoneRegexValid) and afdPhonePceValid.

Important: It is essential that you include both of these directives. If you only use afdPhonePceValid you will request validation from PCE on each keystroke which will raise excessive charges.

You can optionally provide a [country] (ISO2). This is the country that the control will assume if no country code is input. Specifying a country when typing, either using + or 00 at the beginning of the number will override this option.

<div class="form-control">
  <label>Phone Number</label>
  <input 
    type="tel"
    [country]="'GB'"
    afdPhoneSyntaxValid
    afdPhonePceValid
    [(ngModel)]="phone"
    #phoneControl="ngModel"
  >
  <span class="error" *ngIf="phoneControl.hasError('afdPhoneRegexValid')">
    {{ phoneControl.errors!['afdPhoneRegexValid'].message }}
  </span>
  <span class="error" *ngIf="phoneControl.hasError('afdPhonePceValid')">
    {{ phoneControl.errors!['afdPhonePceValid'].message }}
  </span>
</div>
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { 
  AfdPhoneRegexValidDirective,
  AfdPhonePceValidDirective,
  AFDPhoneService
} from '@afd-software/pce-angular';

@Component({
  standalone: true,
  imports: [
    FormsModule,
    AfdPhoneRegexValidDirective,
    AfdPhonePceValidDirective
  ]
})
export class PhoneComponent {
  phone = '';
  
  constructor(private afdPhoneService: AFDPhoneService) {
    this.afdPhoneService.setOptions({
      id: 'YOUR_ID',
      token: 'YOUR_TOKEN'
    });
  }
}

Phone Directive Inputs

| Input | Type | Description | |-------|------|-------------| | country | string | Default country (ISO2 code, e.g., 'GB', 'US') | | id | string | Unique identifier when using multiple phone fields | | excludeCountries | string[] | Countries to exclude from the dropdown | | onlyCountries | string[] | Only show these countries | | preferredCountries | string[] | Countries to show at the top of the list |

Phone Additional Information

It is possible to know some things about a phone number even before it has been input in its entirety. We allow access to this via an Observable on the AFDPhoneService.

import { Component, OnInit, OnDestroy } from '@angular/core';
import { AFDPhoneService } from '@afd-software/pce-angular';
import { Subscription } from 'rxjs';

@Component({...})
export class PhoneComponent implements OnInit, OnDestroy {
  phoneInfoSubscription: Subscription;
  phoneInfo: any;
  
  constructor(private afdPhoneService: AFDPhoneService) {}
  
  ngOnInit() {
    this.phoneInfoSubscription = this.afdPhoneService.phoneInfo.subscribe(data => {
      this.phoneInfo = data;
    });
  }
  
  ngOnDestroy() {
    this.phoneInfoSubscription?.unsubscribe();
  }
}

The full phoneInfo object:

phoneInfo: {
  pceValid: boolean;              // PCE validation result
  syntaxValid: boolean;           // Syntax validation result
  regexValid: boolean;            // Regex validation result (alias for syntaxValid)
  country: string;                // Country ISO2 code
  isMobile: boolean;              // Is mobile number
  isLandLine: boolean;            // Is landline number
  numberType: string;             // Number type (MOBILE, FIXED_LINE, etc.)
  phoneNumber: string;            // The phone number
  phoneNumberE164: string;        // E.164 format
  phoneNumberInternational: string; // International format
  phoneNumberNational: string;    // National format
  phoneNumberRfc3966: string;     // RFC3966 format
}

Email Address Validation

Email validation happens via two attribute directives that are added to an input control.

Email Validation

As each call to PCE is charged for we do not want to send validation requests for email addresses that are clearly not valid. As such, we first try to validate the email address via Regex and only when the pattern is valid do we request validation from PCE.

For this we have two attribute directives afdEmailRegexValid and afdEmailPceValid.

Important: It is essential that you include both of these directives. If you only use afdEmailPceValid you will request validation from PCE on each keystroke which will raise excessive charges.

<div class="form-control">
  <label>Email Address</label>
  <input 
    type="email"
    afdEmailRegexValid
    afdEmailPceValid
    [(ngModel)]="email"
    #emailControl="ngModel"
  >
  <span class="error" *ngIf="emailControl.hasError('afdEmailRegexValid')">
    {{ emailControl.errors!['afdEmailRegexValid'].message }}
  </span>
  <span class="error" *ngIf="emailControl.hasError('afdEmailPceValid')">
    {{ emailControl.errors!['afdEmailPceValid'].message }}
  </span>
</div>
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { 
  AfdEmailRegexValidDirective,
  AfdEmailPceValidDirective,
  AFDEmailService
} from '@afd-software/pce-angular';

@Component({
  standalone: true,
  imports: [
    FormsModule,
    AfdEmailRegexValidDirective,
    AfdEmailPceValidDirective
  ]
})
export class EmailComponent {
  email = '';
  
  constructor(private afdEmailService: AFDEmailService) {
    this.afdEmailService.options = {
      id: 'YOUR_ID',
      token: 'YOUR_TOKEN'
    };
  }
}

Email Additional Information

It is possible to know some extra things about an email address. We allow access to this via an Observable on the AFDEmailService.

import { Component, OnInit, OnDestroy } from '@angular/core';
import { AFDEmailService } from '@afd-software/pce-angular';
import { Subscription } from 'rxjs';

@Component({...})
export class EmailComponent implements OnInit, OnDestroy {
  emailInfoSubscription: Subscription;
  emailInfo: any;
  
  constructor(private afdEmailService: AFDEmailService) {}
  
  ngOnInit() {
    this.emailInfoSubscription = this.afdEmailService.emailInfo.subscribe(data => {
      this.emailInfo = data;
    });
  }
  
  ngOnDestroy() {
    this.emailInfoSubscription?.unsubscribe();
  }
}

The full emailInfo object:

emailInfo: {
  pceValid: boolean;           // PCE validation result
  regexValid: boolean;         // Regex validation result
  pceValidationMessage: string; // PCE validation message
  emailAddress: string;        // The email address
  acceptsAll: boolean;         // Domain accepts all emails
  dummy: boolean;              // Is a dummy/test email
  formatVerified: string;      // Format verification status
  generic: boolean;            // Is a generic email (info@, etc.)
  localChecked: boolean;       // Local part was checked
  nonStandard: boolean;        // Non-standard email format
  reachable: boolean;          // Email is reachable
  status: string;              // Validation status
  suggested: string;           // Suggested correction
  spelling: boolean;           // Spelling issue detected
  throwaway: boolean;          // Is a throwaway/disposable email
}

Angular Material

If you are using the Angular Material design framework, we have a prebuilt module with Material-styled components.

First install the @afd-software/pce-angular-material module. This is in addition to the base @afd-software/pce-angular module.

npm install --save @afd-software/pce-angular-material

Material Email Validation Example

<mat-form-field>
  <mat-label>Email Address</mat-label>
  <input 
    matInput
    type="email"
    afdEmailRegexValid
    afdEmailPceValid
    [(ngModel)]="email"
    #emailControl="ngModel"
  >
  <mat-error *ngIf="emailControl.hasError('afdEmailRegexValid')">
    {{ emailControl.errors!['afdEmailRegexValid'].message }}
  </mat-error>
  <mat-error *ngIf="emailControl.hasError('afdEmailPceValid')">
    {{ emailControl.errors!['afdEmailPceValid'].message }}
  </mat-error>
</mat-form-field>

Material Phone Validation Example

<mat-form-field>
  <mat-label>Phone Number</mat-label>
  <input 
    matInput
    type="tel"
    [country]="'GB'"
    afdPhoneSyntaxValid
    afdPhonePceValid
    [(ngModel)]="phone"
    #phoneControl="ngModel"
  >
  <mat-error *ngIf="phoneControl.hasError('afdPhoneRegexValid')">
    {{ phoneControl.errors!['afdPhoneRegexValid'].message }}
  </mat-error>
  <mat-error *ngIf="phoneControl.hasError('afdPhonePceValid')">
    {{ phoneControl.errors!['afdPhonePceValid'].message }}
  </mat-error>
</mat-form-field>

Exported Types

The library exports several TypeScript types for better type safety:

import type {
  AFDTypeaheadOptions,
  AFDEmailValidationOptions,
  AFDPhoneValidationOptions,
  AFDCardValidationOptions,
  AFDAccountValidationOptions,
  CountryISO,
  PCELookupItem,
  PCERetrieveItem,
  PCEEmailItem,
  PCECardItem,
  PCEAccountItem,
  PCEResponse
} from '@afd-software/pce-angular';

Complete Directive Reference

Address Lookup Directives

| Directive | Selector | Description | |-----------|----------|-------------| | AfdTypeaheadFormDirective | [afdTypeaheadForm] | Container directive that provides the typeahead service | | AfdTypeaheadDirective | input[afdTypeahead] | Input directive for address search | | AfdAddressFieldInputDirective | input[afdAddressFieldInput] | Reactively populates input with PCE field value (recommended) | | AfdCountriesDirective | [afdCountries] | Populates country list | | AfdReverseGeocodeDirective | [afdReverseGeocode] | Triggers reverse geocoding |

Validation Directives

| Directive | Selector | Description | |-----------|----------|-------------| | AfdEmailRegexValidDirective | [afdEmailRegexValid] | Email format validation | | AfdEmailPceValidDirective | [afdEmailPceValid] | Email PCE validation | | AfdPhoneRegexValidDirective | input[afdPhoneRegexValid], input[afdPhoneSyntaxValid] | Phone syntax validation | | AfdPhonePceValidDirective | [afdPhonePceValid] | Phone PCE validation | | AfdCardRegexValidDirective | [afdCardRegexValid] | Card number format validation | | AfdExpiryRegexValidDirective | [afdExpiryRegexValid] | Expiry date format validation | | AfdCardPceValidDirective | [afdCardPceValid] | Card PCE validation (form-level) | | AfdAccountRegexValidDirective | [afdAccountRegexValid] | Account number format validation | | AfdSortRegexValidDirective | [afdSortRegexValid] | Sort code format validation | | AfdAccountPceValidDirective | [afdAccountPceValid] | Account PCE validation (form-level) |

Components

| Component | Selector | Description | |-----------|----------|-------------| | AFDTypeaheadComponent | afd-typeahead-component | Pre-built typeahead component | | AfdManualInputComponent | afd-manual-input-component | Manual input button | | AfdSearchAgainComponent | afd-search-again-component | Search again button | | AfdAddressSearchComponent | afd-manual-input-address-search-component | Address search button |


We Are Here to Help

If you have any questions or need assistance, please contact the AFD Support team:


AFD Software Limited - The Postcode People