@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
Maintainers
Readme
Angular Integration Manual
Contents
- Introduction
- Compatibility
- Migration Guide
- Install and Setup
- Address Lookup
- Credit Card Validation
- Bank Account Validation
- Phone Number Validation
- Email Address Validation
- Angular Material
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
AfdPceAngularModuleis deprecated – import standalone directives directly instead - Uses Angular's signals for reactive state management
- Requires
@angular/cdkfor 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@latestYou will also need to install @angular/cdk if you haven't already:
npm install @angular/cdkStep 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
afdCardPceValidyou 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
afdAccountPceValidyou 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
afdPhonePceValidyou 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
afdEmailPceValidyou 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-materialMaterial 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:
- Website: https://www.afd.co.uk
- Email: [email protected]
- Documentation: https://www.afd.co.uk/developers/
AFD Software Limited - The Postcode People
