web
You’re offline. This is a read only version of the page.
close
Skip to main content
Community site session details

Community site session details

Session Id :

[Integration] Predictive Address Capture in Dynamics 365 using Kleber by DataTools

Nadeeja Bomiriya Profile Picture Nadeeja Bomiriya 6,804

Kleber Address Validation

Kleber Predictive Address Capture is a service provided by DataTools.  In this article, I will walk you through, how to create a custom web resource to integrate with Kleber and also provide the predictive address search user experience on a Dynamics 365 (CRM) form.

The predictive address search is a two step process.

  1. Search for a set of addresses based on the partially entered text.
  2. Read the full address details of the selected address

Below diagram details the complete process.

Kleber Address Validation Process Flow

Resources

You would need to download the below JavaScript and CSS files.

jQuery – https://code.jquery.com/jquery-1.9.1.js

jQuery UI (the version I used is jQuery UI Core 1.10.2) – http://jqueryui.com/download/

All the source files I used can be found in below GitHub repository.

https://github.com/dyn365apps/kleberdyn365

Source Code

HTML and CSS

We need to create a HTML web resource which includes an input element to collect partial address text, JavaScript to call the Kleber Services, and CSS to update the UI to match Dynamics 365 (CRM) UI.

HTML

<body style="margin: 0px; word-wrap: break-word;">
    <form style="margin-bottom: 0px;">
        <table id="allfields" border="0" cellspacing="0" cellpadding="0" width="100%" style="margin-top: 2px">
            <tbody>
                <tr>
                    <td style="font-family: Segoe\000020UI,Tahoma,Arial; font-size: 12px; width:150; max-width: 150px; text-align: left; color: #444444; padding: 0px;">Postal Address</td>
                    <td style="font-family: Segoe\000020UI,Tahoma,Arial; font-size: 12px; width:auto; text-align: left; color: #444444; padding: 0px; padding-left: 26px;">
                        <input style="font-family: Segoe\000020UI,Tahoma,Arial; font-size: 12px; font-weight: bold; color: #000000; width:100%; margin-left:1px; height: 24px;" class="textbox ui-autocomplete-input" size="50" name="Address line 1" id="addline" autocomplete="off" type="text" value="--">
                        <span role="status" aria-live="polite" class="ui-helper-hidden-accessible">10 results are available, use up and down arrow keys to navigate.</span>
                    </td>
                </tr>
            </tbody>
        </table>
    </form>
</body>

CSS

<style>
    #addline {
        border: 0px solid;
        background-color: #ffffff;
        height: 24px;
    }

    #addline:focus {
        outline: 1px solid #CCCCCC;
        background-color: #ffffff;
        padding-left: 5px;
    }

    #addline:hover {
        outline: 1px solid #CCCCCC;
        outline-offset: -2px;
        background-color: #eeeeee;
        padding-left: 5px;
    }

    #addline:active {
        outline: 1px solid #CCCCCC;
        background-color: #ffffff;
        padding-left: 5px;
    }
</style>

GetRequestKey

Every subscribed user has a unique RequestKey.  You need to login to your Kleber account, and you can get your RequestKey.  This function is simply returns the RequestKey when called.

function getRequestKey() {
    var RequestKey = "RK-33333-33333-44444-55555-55555-44444-33333-33333";
    return RequestKey;
}

LoadAddressOnForm

LoadAddressOnForm is called inside $(document).ready.  This will read the values in Dynamics 365 (CRM) address fields, concatenate the fields, and add to addline input element.

dyn365appsAddressMethods.LoadAddressOnForm = function () {
    var address = "--";
    if (parent.Xrm.Page.getAttribute("address1_line1").getValue() != null) {
        address = parent.Xrm.Page.getAttribute("address1_line1").getValue();
    }
    if (parent.Xrm.Page.getAttribute("address1_city").getValue() != null) {
        address += ", " + parent.Xrm.Page.getAttribute("address1_city").getValue();
    }
    if (parent.Xrm.Page.getAttribute("address1_stateorprovince").getValue() != null) {
        address += ", " + parent.Xrm.Page.getAttribute("address1_stateorprovince").getValue();
    }
    if (parent.Xrm.Page.getAttribute("address1_postalcode").getValue() != null) {
        address += ", " + parent.Xrm.Page.getAttribute("address1_postalcode").getValue();
    }
    if (parent.Xrm.Page.getAttribute("address1_country").getValue() != null) {
        address += ", " + parent.Xrm.Page.getAttribute("address1_country").getValue();
    }

    $('#addline').val(address);
};

DataTools.Capture.Address.Predictive.AuPaf.SearchAddress

When the user starts typing the address, DataTools.Capture.Address.Predictive.AuPaf.SearchAddress Method is called to get a list of matching addresses.  You can limit the numbers addresses returned by changing the ResultLimit parameter.

source: function (request, response) {

    $.ajax(
    {
        url: "https://kleber.datatoolscloud.net.au/KleberWebService/DtKleberService.svc/ProcessQueryStringRequest",
        dataType: "jsonp",
        type: "GET",
        contentType: "application/json; charset=utf-8",
        data: { OutputFormat: "json", ResultLimit: 4, AddressLine: request.term, Method: "DataTools.Capture.Address.Predictive.AuPaf.SearchAddress", RequestKey: TempKey },
        success: function (data) {
            response($.map(data.DtResponse.Result, function (item) {

                var Output = (item.AddressLine + ", " + item.Locality + ", " + item.State + ", " + item.Postcode);
                return { label: Output, value: Output, Output: Output, RecordId: item.RecordId, AddressLine: item.AddressLine };
            }));
        }
    });
}

DataTools.Capture.Address.Predictive.AuPaf.RetrieveAddress

When you click on one of the returned addresses, DataTools.Capture.Address.Predictive.AuPaf.RetrieveAddress Method is called to get full address details.  Once, the full address details are retrieved, the Dynamics 365 (CRM) form’s address fields are populated with the retrieve addresses components.  User then saves the record.

select: function (event, ui) {
    $.ajax(
    {
        url: "https://kleber.datatoolscloud.net.au/KleberWebService/DtKleberService.svc/ProcessQueryStringRequest",
        dataType: "jsonp",

        crossDomain: true,
        data: { OutputFormat: "json", RecordId: ui.item.RecordId, Method: "DataTools.Capture.Address.Predictive.AuPaf.RetrieveAddress", RequestKey: TempKey },
        success: function (data) {
            $.map(data.DtResponse.Result, function (item) {
                parent.Xrm.Page.getAttribute("address1_line1").setValue(ui.item.AddressLine);
                parent.Xrm.Page.getAttribute("address1_city").setValue(item.Locality);
                parent.Xrm.Page.getAttribute("address1_stateorprovince").setValue(item.State);
                parent.Xrm.Page.getAttribute("address1_postalcode").setValue(item.Postcode);
                parent.Xrm.Page.getAttribute("address1_country").setValue("AUSTRALIA");
                parent.Xrm.Page.getAttribute("dyn365apps_dpid").setValue(item.DPID);
                parent.Xrm.Page.getAttribute("dyn365apps_addressvalidated").setValue("425320001"); // Valid Address

                var address = parent.Xrm.Page.getAttribute("address1_line1").getValue();
                address += ", " + parent.Xrm.Page.getAttribute("address1_city").getValue();
                address += ", " + parent.Xrm.Page.getAttribute("address1_stateorprovince").getValue();
                address += ", " + parent.Xrm.Page.getAttribute("address1_postalcode").getValue();
                address += ", " + parent.Xrm.Page.getAttribute("address1_country").getValue();
                $('#addline').val(address);
            });
        }
    });
}

Issue

There was an issue, when users type a partial address and hit enter key.  The web resource showed 404 error.  To resolve this below fix was implemented.

$(document).ready(function (e) {
    dyn365appsAddressMethods.LoadAddressOnForm();

    // Stop form submission on enter key press
    $(window).keydown(function (event) {
        if (event.keyCode == 13) {
            event.preventDefault();
            return false;
        }
    });

});

Add Web Resource to Dynamics 365 (CRM) Form

Create a HTML web resource record in Dynamics 365 (CRM) and include the complete code as shown below.

Add the web resource to the form.

Save and Publish.

Conclusion

Once published, you can open the form (in my example, I used the Lead form) and start typing inside the input element.  The result should look like this.

Predictive Address Search

Complete source code

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>dyn365apps - Address Validation</title>
    <link href="/WebResources/dyn365apps_autocomplete_style.css" rel="stylesheet">
    <script src="/WebResources/dyn365apps_jquery1.9.1.js"></script>
    <script src="/WebResources/dyn365apps_jquery_autocomplete_all.js"></script>
    <script>
        function getRequestKey() {
            var RequestKey = "RK-33333-33333-44444-55555-55555-44444-33333-33333";
            return RequestKey;
        }

        dyn365appsAddressMethods = new Object();
        dyn365appsAddressMethods.LoadAddressOnForm = function () {
            var address = "--";
            if (parent.Xrm.Page.getAttribute("address1_line1").getValue() != null) {
                address = parent.Xrm.Page.getAttribute("address1_line1").getValue();
            }
            if (parent.Xrm.Page.getAttribute("address1_city").getValue() != null) {
                address += ", " + parent.Xrm.Page.getAttribute("address1_city").getValue();
            }
            if (parent.Xrm.Page.getAttribute("address1_stateorprovince").getValue() != null) {
                address += ", " + parent.Xrm.Page.getAttribute("address1_stateorprovince").getValue();
            }
            if (parent.Xrm.Page.getAttribute("address1_postalcode").getValue() != null) {
                address += ", " + parent.Xrm.Page.getAttribute("address1_postalcode").getValue();
            }
            if (parent.Xrm.Page.getAttribute("address1_country").getValue() != null) {
                address += ", " + parent.Xrm.Page.getAttribute("address1_country").getValue();
            }

            $('#addline').val(address);
        };

        $(document).ready(function (e) {
            dyn365appsAddressMethods.LoadAddressOnForm();

            // Stop form submission on enter key press
            $(window).keydown(function (event) {
                if (event.keyCode == 13) {
                    event.preventDefault();
                    return false;
                }
            });

        });


        $(function () {
            var TempKey = getRequestKey();
            $('#addline').autocomplete(
            {

                source: function (request, response) {

                    $.ajax(
                    {
                        url: "https://kleber.datatoolscloud.net.au/KleberWebService/DtKleberService.svc/ProcessQueryStringRequest",
                        dataType: "jsonp",
                        type: "GET",
                        contentType: "application/json; charset=utf-8",
                        data: { OutputFormat: "json", ResultLimit: 4, AddressLine: request.term, Method: "DataTools.Capture.Address.Predictive.AuPaf.SearchAddress", RequestKey: TempKey },
                        success: function (data) {
                            response($.map(data.DtResponse.Result, function (item) {

                                var Output = (item.AddressLine + ", " + item.Locality + ", " + item.State + ", " + item.Postcode);
                                return { label: Output, value: Output, Output: Output, RecordId: item.RecordId, AddressLine: item.AddressLine };
                            }));
                        }
                    });
                },

                select: function (event, ui) {
                    $.ajax(
                    {
                        url: "https://kleber.datatoolscloud.net.au/KleberWebService/DtKleberService.svc/ProcessQueryStringRequest",
                        dataType: "jsonp",

                        crossDomain: true,
                        data: { OutputFormat: "json", RecordId: ui.item.RecordId, Method: "DataTools.Capture.Address.Predictive.AuPaf.RetrieveAddress", RequestKey: TempKey },
                        success: function (data) {
                            $.map(data.DtResponse.Result, function (item) {
                                parent.Xrm.Page.getAttribute("address1_line1").setValue(ui.item.AddressLine);
                                parent.Xrm.Page.getAttribute("address1_city").setValue(item.Locality);
                                parent.Xrm.Page.getAttribute("address1_stateorprovince").setValue(item.State);
                                parent.Xrm.Page.getAttribute("address1_postalcode").setValue(item.Postcode);
                                parent.Xrm.Page.getAttribute("address1_country").setValue("AUSTRALIA");
                                parent.Xrm.Page.getAttribute("dyn365apps_dpid").setValue(item.DPID);
                                parent.Xrm.Page.getAttribute("dyn365apps_addressvalidated").setValue("425320001"); // Valid Address

                                var address = parent.Xrm.Page.getAttribute("address1_line1").getValue();
                                address += ", " + parent.Xrm.Page.getAttribute("address1_city").getValue();
                                address += ", " + parent.Xrm.Page.getAttribute("address1_stateorprovince").getValue();
                                address += ", " + parent.Xrm.Page.getAttribute("address1_postalcode").getValue();
                                address += ", " + parent.Xrm.Page.getAttribute("address1_country").getValue();
                                $('#addline').val(address);
                            });
                        }
                    });
                },
            });

        });

    </script>
    <style>
        #addline {
            border: 0px solid;
            background-color: #ffffff;
            height: 24px;
        }

        #addline:focus {
            outline: 1px solid #CCCCCC;
            background-color: #ffffff;
            padding-left: 5px;
        }

        #addline:hover {
            outline: 1px solid #CCCCCC;
            outline-offset: -2px;
            background-color: #eeeeee;
            padding-left: 5px;
        }

        #addline:active {
            outline: 1px solid #CCCCCC;
            background-color: #ffffff;
            padding-left: 5px;
        }
    </style>
    <meta>
    <meta>
    <meta>
    <meta>

</head>
<body style="margin: 0px; word-wrap: break-word;">
    <form style="margin-bottom: 0px;">
        <table id="allfields" border="0" cellspacing="0" cellpadding="0" width="100%" style="margin-top: 2px">
            <tbody>
                <tr>
                    <td style="font-family: Segoe\000020UI,Tahoma,Arial; font-size: 12px; width:150; max-width: 150px; text-align: left; color: #444444; padding: 0px;">Postal Address</td>
                    <td style="font-family: Segoe\000020UI,Tahoma,Arial; font-size: 12px; width:auto; text-align: left; color: #444444; padding: 0px; padding-left: 26px;">
                        <input style="font-family: Segoe\000020UI,Tahoma,Arial; font-size: 12px; font-weight: bold; color: #000000; width:100%; margin-left:1px; height: 24px;" class="textbox ui-autocomplete-input" size="50" name="Address line 1" id="addline" autocomplete="off" type="text" value="--">
                        <span role="status" aria-live="polite" class="ui-helper-hidden-accessible">10 results are available, use up and down arrow keys to navigate.</span>
                    </td>
                </tr>
            </tbody>
        </table>
    </form>
</body>
</html>

Thank you for visiting Dyn365Apps.com.

Follow me on Twitter to get the latest news, tips and tricks and more …

Until next time.

Comments

*This post is locked for comments