Security change on December 1, 2026: TLS 1.2 will become the minimum standard for 365 business Print Agent. Details and system requirements
365 business development
365 business Address Validation

Address Prediction API

Codeunit 5523621 bdev.Address Prediction API drives the type-ahead on a page of your own.

While the user types into a bound field, the app offers matching addresses, and picking one hands you the address in structured form.

Prediction needs three things on your page:

  1. the bdev.Address Autocomplete control add-in, which does the typing and the suggestion list in the browser;
  2. the codeunit, which connects the control to the prediction service;
  3. for a table of your own, a subscriber to OnIsAddressPredictionEnabledForTableNo.

The page: putting it together

The control add-in is one pixel in size and carries no UI of its own - it attaches to the fields you bind to it. A page that offers prediction looks like this:

Code
page 50000 "Broker Card" { SourceTable = Broker; layout { area(Content) { group(General) { field(Name; Rec.Name) { ApplicationArea = All; } field(Address; Rec.Address) { ApplicationArea = All; } field("Address 2"; Rec."Address 2") { ApplicationArea = All; } field("Post Code"; Rec."Post Code") { ApplicationArea = All; } field(City; Rec.City) { ApplicationArea = All; } field(County; Rec.County) { ApplicationArea = All; } field("Country/Region Code"; Rec."Country/Region Code") { ApplicationArea = All; } } usercontrol("bdev.Address Prediction Control"; "bdev.Address Autocomplete") { ApplicationArea = All; trigger OnControlReady() begin AddressPrediction.OnControlAddInReady(Database::Broker, CurrPage."bdev.Address Prediction Control"); end; trigger GetAddressPredictions(fieldName: Text; input: Text) begin AddressPrediction.GetAddressPredictions(fieldName, input, CurrPage."bdev.Address Prediction Control"); end; trigger OnPredictionSelected(fieldName: Text; id: Text) var address: Dictionary of [Text, Text]; begin if (not AddressPrediction.GetSelectedAddressPrediction( address, AddressPrediction.GetAddressType(fieldName), id)) then exit; ApplyAddress(address); end; } } } trigger OnOpenPage() begin AddressPrediction.InitializeAddressPrediction(); end; trigger OnAfterGetRecord() begin BindAddressPredictionFields(); end; trigger OnNewRecord(BelowxRec: Boolean) begin BindAddressPredictionFields(); end; local procedure BindAddressPredictionFields() var fieldNames: Dictionary of [Text, Enum "bdev.Address Prediction Type"]; begin // look up businesses while the user types into "Name" fieldNames.Add(Rec.FieldName(Name), Enum::"bdev.Address Prediction Type"::Establishment); // look up addresses while the user types into "Address" fieldNames.Add(Rec.FieldName(Address), Enum::"bdev.Address Prediction Type"::Address); AddressPrediction.BindAddressPrediction(fieldNames, CurrPage."bdev.Address Prediction Control"); end; var AddressPrediction: Codeunit "bdev.Address Prediction API"; }

Bind on every record change

The binding lives in the control, not in the record. Bind in OnAfterGetRecord and in OnNewRecord, or the type-ahead stops working as soon as the user moves to another record or creates one.

InitializeAddressPrediction()

Resets the prediction instance. Call it in OnOpenPage, before anything else.

Code
procedure InitializeAddressPrediction()

OnControlAddInReady(Integer, ControlAddIn)

Activates the control once the browser has loaded it, and states which table the page shows.

Code
procedure OnControlAddInReady(tableNo: Integer; control: ControlAddIn "bdev.Address Autocomplete")
ParameterTypeDescription
tableNoIntegerThe table id of the page source. Decides whether prediction is enabled - see Extensibility Events.
controlControlAddIn "bdev.Address Autocomplete"The control of the current page.

Call it from the OnControlReady trigger of the control and from nowhere else - the control is not ready before.

BindAddressPrediction(...)

Binds page fields to the type-ahead. Four overloads, differing only in how much you say about each field:

Code
procedure BindAddressPrediction(fieldNames: Dictionary of [Text, Enum "bdev.Address Prediction Type"]; control: ControlAddIn "bdev.Address Autocomplete") procedure BindAddressPrediction(fieldNames: List of [Text]; control: ControlAddIn "bdev.Address Autocomplete") procedure BindAddressPrediction(fieldName: Text; control: ControlAddIn "bdev.Address Autocomplete") procedure BindAddressPrediction(fieldName: Text; addrPreditionType: Enum "bdev.Address Prediction Type"; control: ControlAddIn "bdev.Address Autocomplete")
ParameterTypeDescription
fieldName / fieldNamesText, List or DictionaryThe field name as the page knows it. Use Rec.FieldName(...) rather than a literal, so a rename cannot break the binding silently.
addrPreditionTypeEnum "bdev.Address Prediction Type"Address or Establishment. The overloads without it bind as Address.
controlControlAddIn "bdev.Address Autocomplete"The control of the current page.

Binding a field that is already bound rebinds it - the codeunit unbinds it first - so calling the binding again on every record change is safe.

UnbindAddressPrediction(Text, ControlAddIn)

Removes the type-ahead from a field, for example when your page turns it off for a record.

Code
procedure UnbindAddressPrediction(fieldName: Text; control: ControlAddIn "bdev.Address Autocomplete")

GetAddressPredictions(Text, Text, ControlAddIn)

Fetches the suggestions for the current input and hands them to the control, which shows them.

Code
procedure GetAddressPredictions(fieldName: Text; input: Text; control: ControlAddIn "bdev.Address Autocomplete")
ParameterTypeDescription
fieldNameTextThe field the user is typing into, as passed by the trigger.
inputTextWhat the user has typed so far.
controlControlAddIn "bdev.Address Autocomplete"The control of the current page.

Call it from the GetAddressPredictions trigger of the control. It fires on every keystroke, so do not put work of your own around it.

GetSelectedAddressPrediction(Dictionary, Enum, Text)

Resolves the suggestion the user picked into the address behind it.

Code
procedure GetSelectedAddressPrediction(var address: Dictionary of [Text, Text]; addressType: Enum "bdev.Address Prediction Type"; id: Text): Boolean
ParameterTypeDescription
addressDictionary of [Text, Text]The address of the suggestion.
addressTypeEnum "bdev.Address Prediction Type"The type the field was bound as. GetAddressType answers it for a field name.
idTextThe id of the suggestion, as passed by the trigger.

Returns false when the address could not be fetched.

The dictionary carries the parts of the address the service knows. Not every key is present - a rural address without a street number has no address, and the business keys only appear for an Establishment. Ask with ContainsKey before reading:

KeyContent
addressStreet and house number.
address2Additional address information.
cityCity.
postalCodePost code.
countyRegion, state or county.
countryCodeISO alpha-2 country code.
companyNameName of the business. Establishment only.
phoneNumberInternational phone number. Establishment only.
homePageWebsite, reduced to the domain. Establishment only.
Code
local procedure ApplyAddress(address: Dictionary of [Text, Text]) begin if (address.ContainsKey('countryCode')) then Rec.Validate("Country/Region Code", CopyStr(address.Get('countryCode'), 1, MaxStrLen(Rec."Country/Region Code"))); if (address.ContainsKey('address')) then Rec.Validate(Address, CopyStr(address.Get('address'), 1, MaxStrLen(Rec.Address))); if (address.ContainsKey('postalCode')) then Rec.Validate("Post Code", CopyStr(address.Get('postalCode'), 1, MaxStrLen(Rec."Post Code"))); if (address.ContainsKey('city')) then Rec.Validate(City, CopyStr(address.Get('city'), 1, MaxStrLen(Rec.City))); if (address.ContainsKey('county')) then Rec.Validate(County, CopyStr(address.Get('county'), 1, MaxStrLen(Rec.County))); CurrPage.Update(true); end;

Validate Country/Region Code first: the format of the other fields depends on the country.

GetAddressType(Text)

Returns the type a field was bound as, so that the selection trigger can pass it on without keeping its own state.

Code
procedure GetAddressType(fieldName: Text): Enum "bdev.Address Prediction Type"

See also

Last modified on