Load BusinessProcessFlow thru JavaScript in Dynamics 365

There is a known defect loading active Business Process Flow on the Form, when you upgrade from CRM 2016 to Dynamics 365. It does not load for some records which came thru ETL. If you check in Advanced Find including Process Id column, Process Id is NULL for these records.

If you want to show BPF for these records which Process id is NULL, you need to call following JS in the form load event.

function setProcessId() {
var processId = Xrm.Page.context.getQueryStringParameters().process;
if (processId == null) {
//Business Process Flow Id
var procesGuid = '03278623-2923-443A-957C-AF56D1B1FC81';
Xrm.Page.data.process.setActiveProcess(procesGuid, function callbackFunction() { });
}
}
Advertisements

How to use Auto Complete in CRM 2016

Introduction

Dynamics CRM 2016 comes with new scripting features for Auto Complete, which allows to configure auto complete feature for single line text fields.
We can now use JavaScript code to configure the auto-completion experience in CRM by using the following client-side APIs introduced in Microsoft Dynamics CRM Online 2016 Update and Microsoft Dynamics CRM 2016 (on-premises): getValueKeypress methods, and Auto-completion methods.

How to Configure Auto Complete

Let us take an example to provide an auto complete list of States for the State field on Contact form.

To enable Auto complete functionality work on Contact form State field, we need to call the function on the contact form load as shown below. In this example, we have called “suggestListOfStates” function on form load as shown below.



function suggestListOfStates() {
    states = [
           { state: 'Andaman and Nicobar Islands', capital: 'Port Blair', code: '1' },
           { state: 'Andhra Pradesh', capital: 'Vijayawada', code: '2' },
           { state: 'Arunachal Pradesh', capital: 'Itanagar', code: '3' },
           { state: 'Assam', capital: 'Dispur', code: '4' },
           { state: 'Bihar', capital: 'Patna', code: '5' },
           { state: 'Chandigarh', capital: 'Chandigarh', code: '6' },
           { state: 'Chhattisgarh', capital: 'Raipur', code: '7' },
           { state: 'Dadra and Nagar Haveli', capital: 'Silvassa', code: '8' },
           { state: 'Daman and Diu', capital: 'Daman', code: '9' },
           { state: 'National Capital Territory of Delhi', capital: 'Delhi', code: '10' },
           { state: 'Goa', capital: 'Panaji', code: '11' },
           { state: 'Gujarat', capital: 'Gandhinagar', code: '12' },
           { state: 'Haryana', capital: 'Chandigarh', code: '13' },
           { state: 'Himachal Pradesh', capital: 'Shimla', code: '14' },
           { state: 'Jammu and Kashmir', capital: 'Srinagar (S) and Jammu(W)', code: '15' },
           { state: 'Jharkhand', capital: 'Ranchi', code: '16' },
           { state: 'Karnataka', capital: 'Bengaluru', code: '17' },
           { state: 'Kerala', capital: 'Thiruvananthapuram', code: '18' },
           { state: 'Lakshadweep', capital: 'Kavaratti', code: '19' },
           { state: 'Madhya Pradesh', capital: 'Bhopal', code: '20' },
           { state: 'Maharashtra', capital: 'Mumbai', code: '21' },
           { state: 'Manipur', capital: 'Imphal', code: '22' },
           { state: 'Meghalaya', capital: 'Shillong', code: '23' },
           { state: 'Mizoram', capital: 'Aizawl', code: '24' },
           { state: 'Nagaland', capital: 'Kohima', code: '25' },
           { state: 'Orissa', capital: 'Bhubaneswar', code: '26' },
           { state: 'Pondicherry', capital: 'Pondicherry', code: '27' },
           { state: 'Punjab', capital: 'Chandigarh', code: '28' },
           { state: 'Rajasthan', capital: 'Jaipur', code: '29' },
           { state: 'Sikkim', capital: 'Gangtok', code: '30' },
           { state: 'Tamil Nadu', capital: 'Chennai', code: '31' },
           { state: 'Telangana', capital: 'Hyderabad', code: '32' },
           { state: 'Tripura', capital: 'Agartala', code: '33' },
           { state: 'Uttar Pradesh', capital: 'Lucknow', code: '34' },
           { state: 'West Bengal', capital: 'Kolkata', code: '35' }
    ];
    var keyPressFcn = function (ext) {

        try {
            var userInput = Xrm.Page.getControl("address1_stateorprovince").getValue();
            resultSet = {
                results: new Array(),
            };
            var userInputLowerCase = userInput.toLowerCase();
            for (i = 0; i < states.length; i++) {                 if (userInputLowerCase === states[i].state.substring(0, userInputLowerCase.length).toLowerCase()) {                     resultSet.results.push({                         id: i,                         fields: [states[i].state, states[i].capital ]                     });                 }                 if (resultSet.results.length >= 10) break;
            }
            if (resultSet.results.length > 0) {
                ext.getEventSource().showAutoComplete(resultSet);
            } else {
                ext.getEventSource().hideAutoComplete();
            }
        } catch (e) {
            console.log(e);
        }
    };
    Xrm.Page.getControl("address1_stateorprovince").addOnKeyPress(keyPressFcn);
}

New JavaScript Auto Complete Methods

Use the showAutoComplete and hideAutoComplete methods to configure the auto-completion experience in text controls in forms.

showAutoComplete

Use this to show up to 10 matching strings in a drop-down list as users press keys to type character in a specific text field. You can also add a custom command with an icon at the bottom of the drop-down list. On selecting an item in the drop-down list, the value in the text field changes to the selected item, the drop-down list disappears, and the OnChange event for the text field is invoked.


Xrm.Page.getControl(arg).showAutoComplete(object)

hideAutoComplete

Use this function to hide the auto-completion drop-down list you configured for a specific text field.


Xrm.Page.getControl(arg).hideAutoComplete()

We don’t have to explicitly use the hideAutoComplete method because, by default, the drop-down list hides automatically if the user clicks elsewhere or if a new drop-down list is displayed. This function is available in case developers need to explicitly hide the auto-completion drop-down list to handle a custom scenario.

New JavaScript Keypress Methods

Use addOnKeyPress, removeOnKeyPress, and fireOnKeyPress methods to provide immediate feedback or take actions as user types in a control. These methods enable you to perform data validations in a control even before the user commits (saves) the value in a form.

addOnKeyPress

Use this to add a function as an event handler for the keypress event so that the function is called when you type a character in the specific text or number field.

Xrm.Page.getControl(arg).addOnKeyPress([function reference])
Xrm.Page.getControl("address1_stateorprovince").addOnKeyPress(keyPressFcn);

removeOnKeyPress

Use this to remove an event handler for a text or number field that you added using addOnKeyPress.

Xrm.Page.getControl(arg).removeOnKeyPress([function reference])

fireOnKeyPress

Use this to manually fire an event handler that you created for a specific text or number field to be executed on the keypress event.

Xrm.Page.getControl(arg).fireOnKeyPress()

Dynamics CRM 2011 JavaScript debugging in Internet Explorer 11

Microsoft rebuilt the F12 tools from the ground up in Internet Explorer11. They have a brand new UI and new functionality to make your developing and debugging faster and easier.

You can access them from within a browser window by hitting F12. If your keyboard doesn’t have function keys, you can select ‘F12 developer tools’ from the ‘Tools’ menu.

You can use the Debugger tool to examine what your code is doing, when it’s doing it, and how it’s doing it. Pause code in mid-execution, step through it line-by-line, and watch the state of variables and objects at each step. New features in the Debugger tool include:

  • No-refresh debugging. Set your breakpoints  and go without reloading and losing state.
  • Tabbed document interface for easier management of multiple scripts.
  • Scrollbar that highlights breakpoints and search matches.

Development and debugging tasks it makes easier:

  • Seeing what led to a function call using the Callstack.
  • Making compressed or minified code more readable.
  • Monitoring web worker creation and  execution.

There are eight distinct tools, each with their own tab in the F12 tools interface. Here you’ll find an image of each tool, a quick summary of what it does and what’s new, and a couple of typical development or debugging tasks the tool makes easier. Check the link ‘Using the F12 developer tools in Internet Explorer 11’ http://msdn.microsoft.com/en-us/library/ie/bg182326(v=vs.85).aspx

Here are the steps how to debug Dynamics CRM JavaScript code in Internet Explorer11.

Step1:  Before you try to debug JavaScript code make sure ‘Disable script debugging (Internet Explorer)’ and ‘Disable script debugging (Other)’ options are un-checked in ‘Advanced’ tab of Internet Explorer options, these options are checked by default.

JSDebugging1

Step2:  Press the F12 key on your keyboard to open the tools or select ‘F12 developer tools’ from the ‘Tools’ menu.  You will see ‘DOM Explorer tool (CTRL + 1)’ left side, click on ‘Debugger (CTRL+3)’

JSDebugging2

Step3:  Click on ‘Open Document (CTRL+O)’ and check CRM page.

JSDebugging3

Step4:  Expand CRM page in ‘Open Document (CTRL+O)’ and check your JavaScript file is loaded and click on your JavaScript file and set the debugger wherever you want

JSDebugging4

JSDebugging5

JavaScript references in Microsoft Dynamics CRM 2013

The JavaScript object model is the JavaScript API that CRM provides to enable you to customize various behaviors based on events and to access CRM data that is present on a form.

CRM 2013 fully supports the JavaScript object model from the previous version; however, it does not support the JavaScript object model from Microsoft Dynamics CRM 4.0.

Check out following reference documentation for client-side events and object models that can be used with JavaScript libraries. * marked is new in CRM 2013.

Xrm.Utility: Xrm.Utility object provides a container for useful functions not directly related to the current page. The following table lists the functions of Xrm.Utility.

Xrm.Utility
alertDialog Displays   a dialog box with a message.
confirmDialog Displays   a confirmation dialog box that contains a message as well as OK and Cancel   buttons.
isActivityType Determine   if an entity is an activity entity.
openEntityForm Opens   an entity form.
openWebResource Opens   an HTML web resource.

Xrm.Page.data: Xrm.Page.data provides an entity object that provides collections and methods to manage data within the entity form. The following tables lists the functions of Xrm.Page.data and Xrm.Page.data.entity

Xrm.Page.data
getIsValid* Do a validation check for the data in   the form.
refresh* Asynchronously refresh all the data of the form without reloading the page.
save* Saves the record asynchronously with the option to set callback functions.
Xrm.Page.data.entity
addOnSave Adds a function to be called when the record is saved.
getDataXml Returns a string representing the xml that will be sent to the server when the record is saved.
getEntityName Returns a string representing the  logical name of the entity for the record.
getId Returns a string representing the GUID   id value for the record.
getIsDirty Returns a Boolean value that indicates if any fields in the form have been modified.
getPrimaryAttributeValue* Gets a string for the value of the primary attribute of the entity.
removeOnSave Removes a function to be called when the record is saved.
save Saves the record with the options to close or new.

Xrm.Page.context: Xrm.Page.context provides methods to retrieve information specific to an organization, a user, or parameters that were passed to the form in a query string. The following table lists the functions of Xrm.Page.context.

 Xrm.Page.context
client.getClient* Returns a value to indicate which client the script is executing in.
client.getClientState* Returns a value to indicate the state of the client.
getClientUrl Returns the base URL that was used to access the application.
getCurrentTheme Returns a string representing the current Microsoft Office Outlook theme chosen by the user.
getOrgLcid Returns the LCID value that represents   the base language for the organization.
getOrgUniqueName Returns the unique text value of the   organization’s name.
getQueryStringParameters Returns a dictionary object of key   value pairs that represent the query string arguments that were passed to the   page.
getUserId Returns the GUID of the SystemUser.Id value for the current user.
getUserLcid Returns the LCID value that represents the provisioned language that the user selected as their preferred language.
getUserName* Returns the name of the current user.
getUserRoles Returns an array of strings that represent the GUID values of each of the security roles that the user is  associated with.
isOutlookClient (Deprecated) Returns a Boolean value indicating if the user is using Microsoft Dynamics CRM for Outlook.
isOutlookOnline (Deprecated) Returns a Boolean value that indicates whether   the user is connected to the CRM server.
prependOrgName Prepends the organization name to the   specified path.

Xrm.Page.ui:  Xrm.Page.ui provides collections and methods to manage the user interface of the form. The following table lists the functions of Xrm.Page.ui

Xrm.Page.ui
clearFormNotification* Remove form level notifications.
close Method to close the form.
formSelector.getCurrentItem Method to return a reference to the   form currently being shown.
formSelector.items A collection of all the form items accessible to the current user.
getViewPortHeight Method to get the height of the viewport in pixels.
getViewPortWidth Method to get the width of the viewport   in pixels.
getCurrentControl Get the control object that currently has focus.
getFormType Get the form context for the record.
navigation.items A collection of all the navigation items on the page.
setFormNotification* Display form level notifications.
refreshRibbon Re-evaluate the ribbon data that controls what is displayed in it.
 Collections
Xrm.Page.data.entity.attributes All attributes on the page.
Xrm.Page.ui.controls All controls on the page.
Xrm.Page.ui.formSelector.items All the forms available to the user.
Xrm.Page.ui.navigation.items All the items in the form navigation   area.
Xrm.Page.ui.tabs All the tabs on the page.
Xrm.Page Attribute.controls All the controls for the attribute.
Xrm.Page.ui Section.controls All the controls in the section.
Xrm.Page.ui Tab.sections All the sections in the tab.
 Collections Methods
forEach Apply an action in a delegate function to each object in the collection.
get Get one or more object from the collection depending on the arguments passed.
getLength Get the number of items in the collection.

Attributes: Attributes store the data available in the record. Attributes are available from the Xrm.Page.data.entity.attributes collection. To access an attribute you can use the Xrm.Page.data.entity.attributes.get method or the shortcut version Xrm.Page.getAttribute. Following table shows how you can query attribute properties to understand what kind of attribute it is or change the behavior of the attribute.

 Xrm.Page.getAttribute(“…”)
getAttributeType Get the type of attribute.
getFormat Get the attribute format.
getIsDirty Determine whether the value of an   attribute has changed since it was last saved.
getIsPartyList Determine whether a lookup attribute   represents a partylist lookup.
getMaxLength Get the maximum length of string which   an attribute that stores string data can have.
getName Get the name of the attribute.
getParent Get a reference to the Xrm.Page.data.entity object that is the parent to all attributes.
getRequiredLevel Returns a string value indicating   whether a value for the attribute is required or recommended.
getSubmitMode Sets whether data from the attribute   will be submitted when the record is saved. always / never / dirty
getUserPrivilege Determine what privileges a user has   for fields using Field Level Security.
getValue / setValue Gets or Sets the data value for an   attribute.
setRequiredLevel Sets whether data is required or   recommended for the attribute before the record can be saved. none / required  / recommended
setSubmitMode Returns a string indicating when data   from the attribute will be submitted when the record is saved.
Number Attribute Methods
getMax / getMin Returns a number indicating the maximum   or minimum allowed value for an attribute.
getPrecision Returns the number of digits allowed to   the right of the decimal point.
setPrecision* Override the precision set for a number attribute.
DateTime Attribute Methods
setIsAllDay* Specify whether a date control should  set a value including the entire day.
setShowTime* Specify whether a date control should  show the time portion of the date.

Controls: Controls represent the user interface elements in the form. Each attribute in the form will have at least one control associated with it. Not every control is associated with an attribute. IFRAME, web resource, and subgrids are controls that do not have attributes. Controls are available from the Xrm.Page.ui.controls collection. To access a control you can use the Xrm.Page.ui.controls.get method or the shortcut version Xrm.Page.getControl. The following table lists the functions of Controls.

Xrm.Page.getControl(“…”)  
clearNotification* Remove a message already displayed for   a control.
getAttribute Get the attribute that the control is   bound to.
getControlType Get information about the type of   control.
getDisabled / setDisabled Get or Set whether the control is   disabled.
getLabel / setLabel Get or Set the label for the control.
getName Get the name of the control.
getParent Get the section object that the control   is in.
getVisible / setVisible Get or Set a value that indicates   whether the control is currently visible.
setFocus Sets the focus on the control.
setNotification* Display a message near the control to   indicate that data is not valid.

 Lookup Controls: The following table lists the functions of Lookup Control.

addCustomFilter* Use fetchXml to add additional filters   to the results displayed in the lookup. Each filter will be combined with an   ‘AND’ condition.
addCustomView Adds a new view for the lookup dialog   box.
addPreSearch* Use this method to apply changes to   lookups based on values current just as the user is about to view results for   the lookup.
getDefaultView / setDefaultView Get or Set Id value of the default   lookup dialog view.
removePreSearch* Use this method to remove event handler

OptionSet: The following table lists the functions of OptionSet Control.

getInitialValue Returns a value that represents the   value set for an optionset or boolean when the form opened.
getOption[s] Returns an option object with the value   matching the argument passed to the method.
getSelectedOption Returns the option object that is selected.
getText Returns a string value of the text for   the currently selected option for an optionset attribute.
adoption / removeOption Adds or remove an option to an option   set control.
clearOptions Clears all options from an Option Set   control.

IFRAME and Web Resource Controls:  An IFRAME control allows you to include a page within a form by providing a URL. An HTML web resource added to a form is presented using an IFRAME element. Silverlight and image web resources are embedded directly within the page. The following table lists the functions of IFrame or Web Resource controls.

getData / setData Get or Set the value of the data query   string parameter passed to a Silverlight web resource.
getInitialUrl Returns the default URL that an I-frame   control is configured to display. This method is not available for web   resources.
getObject Returns the object in the form that   represents an I-frame or web resource.
getSrc / setSrc Get or Set the current URL being   displayed in an IFrame or web resource.

Sub-Grid Control: Sub-Grid control has refresh method. We can use this method to refresh data displayed in a Sub-Grid.

refresh Refreshes the data displayed in a Sub-Grid.

OnChange Event: There are three methods you can use to work with the OnChange event for an attribute.

addOnChange / removeOnChange Sets or remove a function to be called   when the attribute value is changed.
fireOnChange Causes the OnChange event

Get Form types and modes in Dynamics CRM 2013

getSaveMode(), returns a value indicating how the save event was initiated by the user. The following table describes the supported values returned to detect different ways entity records may be saved by the user in CRM 2013.

execObj.getEventArgs().getSaveMode();
Event Mode Value
Save 1
Save and Close 2
Deactivate 5
Reactivate 6
Send (Email) 7
Disqualify (Lead) 15
Qualify (Lead) 16
Assign (user or team owned entities) 47
Save as Completed (Activities) 58
Save and New 59
AutoSave 70

getFormType(): Method to get the form context for the record. The following table lists the form types that correspond to the return value.

Xrm.Page.ui.getFormType();
Form Type Value
Undefined 0
Create 1
Update 2
Read Only 3
Disabled 4
Quick Create 5
Bulk Edit 6
Read Optimized 11

Custom Rule in Ribbon Customization to enable/disable ribbon button in Dynamics CRM 2011

My requirement is to enable/disable Deactivate ribbon button on Account form based on following condition. In our case CRM gets accounts from other system, if account came from other system to CRM, user should not have capability to deactivate. We have a custom field “ls_cmid” on Account entity, based on this we want enable/disable Deactivate ribbon button. If this field “ls_cmid” value is NULL that means account is created in CRM, if it is not NULL, It came from other system.

Before going thru the steps, hoping you have basic understanding of the RibbonDiffXML.

Step1: Write following JavaScript methods in Account entity script.


//Disable Deactivate ribbon button If account came from CM
function DisableDeactivateButton() {
    var formType = Xrm.Page.ui.getFormType();
    if (formType != 1) {
        var isCMOwned = CheckIfAccountOwnedByCM();
        if (isCMOwned != null && isCMOwned) {
            return false;
        } else {
            return true;
        }
    }
    return true;
}
//Check if Account came from CM or not
function CheckIfAccountOwnedByCM() {
    if (Xrm.Page.getAttribute('ls_cmid') != null) {
        var cmId = Xrm.Page.getAttribute('ls_cmid').getValue();
        if (cmId != null && cmId.length > 0) {
            return true;
        }
    }
    return false;
}

Step2: Create a solution for Account entity and export into your local folder. Unzip the solution folder and open Customizations.XML file

Step3: In the CommandDefinition for Deactivate ribbon button you will see the EnableRules. You can have several rules and if any one of the rules returns False, the button will be disabled. Open Customizatons.XML file in Visual Studio and add new EnableRule  under <EnableRules> in <RuleDefinitions> file.


<EnableRule Id="LS.Mscrm.DisableDeactivateButton">
  <CustomRule FunctionName="DisableDeactivateButton" Library="$webresource:ls_script_account" Default="true" />
</EnableRule>

Step4: Update Deactivate CommandDefination section under <CommandDefinitions> in Customization.XML adding above rule. If you do not have this, you can find the CommandDefination for standard buttons on standard entities in the SDK folder.\sdk\resources\exportedribbonxml\ accountribbon.xml file.


<CommandDefinition Id="Mscrm.Form.Deactivate">
  <EnableRules>
    <EnableRule Id="Mscrm.CanWritePrimary" />
    <EnableRule Id="LS.Mscrm.DisableDeactivateButton" />
  </EnableRules>
  <DisplayRules>
    <DisplayRule Id="Mscrm.CanWritePrimary" />
    <DisplayRule Id="Mscrm.PrimaryIsActive" />
    <DisplayRule Id="Mscrm.PrimaryEntityHasStatecode" />
    <DisplayRule Id="Mscrm.PrimaryIsNotActivity" />
  </DisplayRules>
  <Actions>
    <JavaScriptFunction FunctionName="changeState" Library="/_static/_forms/form.js">
      <StringParameter Value="deactivate" />
      <CrmParameter Value="PrimaryEntityTypeCode" />
      <StringParameter Value="5" />
    </JavaScriptFunction>
  </Actions>
</CommandDefinition>

Make Country and State fields into dropdown list in Dynamics CRM 2011

By default, country and state/province fields in account, contact, lead,competitor and user entities in CRM 2011 are single line textboxes, So It is not user friendly to enter Country and State in these entities.

We do not want to create new fields for country and state with global optionsets, we wanted them to be dropdowns so that user can choose country and state easily.

Following JavaScript code will make the Country field into a dropdown that drives the State/Province field as well.  The State/Province field will be a dropdown for countries that have been configured (USA, Mexico and Canada countries and states are configured here, but it’s easy to add your own).  If a country has not been configured, the State/Province field falls back to the default textbox.

1.Create a new JavaScript Web Resource called CountriesAndStates.js and add following JavaScript code in that.

2.Add latest JQuery web resource(jquery-1.7.1.min.js) in form load, If you do not have latest JQuery file download from http://jquery.com/download/

3.Add a form load event that calls the LoadCountryAndStateFields method, passing in parameters for the name of the country and stateorprovince fields you wish to wire up (see images below).

CountriesAndStates.js

// Configures the country field to be a dropdown based on the Country object.
function LoadCountryField(countryFieldName, stateFieldName) {
    var $countryField = $('#' + countryFieldName);
    if ($countryField.length < 1) return;
    $countryField.hide();
    var selectedCountry = $countryField.val();
    var countryRequirementLevel = Xrm.Page.getAttribute(countryFieldName).getRequiredLevel();
    countryRequirementLevel = countryRequirementLevel == "required" ? 2 : countryRequirementLevel == "recommended" ? 1 : 0;
    var $countryDropdown = generateSelectBox('ddl_' + countryFieldName, countryRequirementLevel, Countries, selectedCountry);
    $('#' + countryFieldName + '_d').append($countryDropdown);
    $countryDropdown.change({ 'countryFieldName': countryFieldName, 'stateFieldName': stateFieldName }, handleCountryChanged);
    document.getElementById('ddl_' + countryFieldName).tabIndex = document.getElementById(countryFieldName).tabIndex;
    LoadStateField(stateFieldName, selectedCountry);
}
// Configures the stateOrProvince field to be a dropdown dependent on the value of the country dropdown. Values are pulled from the Countries object.
function LoadStateField(stateFieldName, selectedCountry) {
    var stateAttr = Xrm.Page.getAttribute(stateFieldName);
    var selectedState = stateAttr == null ? "" : stateAttr.getValue();
    var states = getStatesForCountry(selectedCountry);
    var $stateField = $('#' + stateFieldName);
    if (states == null || !$.isArray(states) || states.length < 1) {
        $('#ddl_' + stateFieldName).remove();
        $stateField.show();
        return;
    }
    $stateField.hide();
    var stateRequirementLevel = Xrm.Page.getAttribute(stateFieldName).getRequiredLevel();
    stateRequirementLevel = stateRequirementLevel == "required" ? 2 : stateRequirementLevel == "recommended" ? 1 : 0;
    var $stateDropdown = generateSelectBox('ddl_' + stateFieldName, stateRequirementLevel, states, selectedState);
    var $existingDropdown = $('#ddl_' + stateFieldName);
    if ($existingDropdown.length < 1)
        $('#' + stateFieldName + '_d').append($stateDropdown);
    else
        $existingDropdown.replaceWith($stateDropdown);
    $stateDropdown.change({ 'stateFieldName': stateFieldName }, handleStateChanged);
    $stateDropdown.change();
    document.getElementById('ddl_' + stateFieldName).tabIndex = document.getElementById(stateFieldName).tabIndex;
}
// Finds the states that go with selectedCountry, using the Countries object.
function getStatesForCountry(selectedCountry) {
    for (i in Countries) {
        var country = Countries[i];
        if (selectedCountry == country.name)
            return country.states;
    }
    return [];
}
// Sets the value of the country field to the newly selected value and reconfigures the dependent state dropdown.
function handleCountryChanged(eventData) {
    var stateFieldName = eventData.data.stateFieldName;
    var selectedCountry = setFieldFromDropdown(eventData.data.countryFieldName);
    LoadStateField(stateFieldName, selectedCountry);
}
// Sets the value of the stateOrProvince field to the newly selected value
function handleStateChanged(eventData) {
    setFieldFromDropdown(eventData.data.stateFieldName);
}
// Sets a field's value based on a related dropdown's value
function setFieldFromDropdown(fieldName) {
    var $dropdown = $('#ddl_' + fieldName);
    if ($dropdown.length != 1) return null;
    var selectedValue = $dropdown.find('option:selected:first').val();
    var attr = Xrm.Page.getAttribute(fieldName);
    if (attr != null) attr.setValue(selectedValue);
    return selectedValue;
}
// Generates a new select box with appropriate attributes for MS CRM 2011.
function generateSelectBox(id, requirementLevel, options, selectedValue) {
    var $ddl = $('<select id="' + id + '" class="ms-crm-SelectBox" req="' + requirementLevel + '" height="4" style="IME-MODE: auto; width: 100%"></select>');
    $ddl.append(jQuery('<option></option').val('').html(''));
    $.each(options, function (i, item) {
        $ddl.append(jQuery('<option></option').val(item.name).html(item.name));
        if (selectedValue == item.name)
            $ddl.find('option:last').attr('selected', 'selected');
    });
    return $ddl;
}
// Global array of countries and their respective states
var Countries = [
                    { "name": "United States", "abbr": "US", "states": [{ "name": "Alabama", "abbr": "AL" },
                                                                        { "name": "Alaska", "abbr": "AK" },
                                                                        { "name": "Arizona", "abbr": "AZ" },
                                                                        { "name": "Arkansas", "abbr": "AR" },
                                                                        { "name": "California", "abbr": "CA" },
                                                                        { "name": "Colorado", "abbr": "CO" },
                                                                        { "name": "Connecticut", "abbr": "CT" },
                                                                        { "name": "Delaware", "abbr": "DE" },
                                                                        { "name": "District Of Columbia", "abbr": "DC" },
                                                                        { "name": "Florida", "abbr": "FL" },
                                                                        { "name": "Georgia", "abbr": "GA" },
                                                                        { "name": "Hawaii", "abbr": "HI" },
                                                                        { "name": "Idaho", "abbr": "ID" },
                                                                        { "name": "Illinois", "abbr": "IL" },
                                                                        { "name": "Indiana", "abbr": "IN" },
                                                                        { "name": "Iowa", "abbr": "IA" },
                                                                        { "name": "Kansas", "abbr": "KS" },
                                                                        { "name": "Kentucky", "abbr": "KY" },
                                                                        { "name": "Louisiana", "abbr": "LA" },
                                                                        { "name": "Maine", "abbr": "ME" },
                                                                        { "name": "Maryland", "abbr": "MD" },
                                                                        { "name": "Massachusetts", "abbr": "MA" },
                                                                        { "name": "Michigan", "abbr": "MI" },
                                                                        { "name": "Minnesota", "abbr": "MN" },
                                                                        { "name": "Mississippi", "abbr": "MS" },
                                                                        { "name": "Missouri", "abbr": "MO" },
                                                                        { "name": "Montana", "abbr": "MT" },
                                                                        { "name": "Nebraska", "abbr": "NE" },
                                                                        { "name": "Nevada", "abbr": "NV" },
                                                                        { "name": "New Hampshire", "abbr": "NH" },
                                                                        { "name": "New Jersey", "abbr": "NJ" },
                                                                        { "name": "New Mexico", "abbr": "NM" },
                                                                        { "name": "New York", "abbr": "NY" },
                                                                        { "name": "North Carolina", "abbr": "NC" },
                                                                        { "name": "North Dakota", "abbr": "ND" },
                                                                        { "name": "Ohio", "abbr": "OH" },
                                                                        { "name": "Oklahoma", "abbr": "OK" },
                                                                        { "name": "Oregon", "abbr": "OR" },
                                                                        { "name": "Pennsylvania", "abbr": "PA" },
                                                                        { "name": "Puerto Rico", "abbr": "PR" },
                                                                        { "name": "Rhode Island", "abbr": "RI" },
                                                                        { "name": "South Carolina", "abbr": "SC" },
                                                                        { "name": "South Dakota", "abbr": "SD" },
                                                                        { "name": "Tennessee", "abbr": "TN" },
                                                                        { "name": "Texas", "abbr": "TX" },
                                                                        { "name": "Utah", "abbr": "UT" },
                                                                        { "name": "Vermont", "abbr": "VT" },
                                                                        { "name": "Virgin Islands", "abbr": "VI" },
                                                                        { "name": "Virginia", "abbr": "VA" },
                                                                        { "name": "Washington", "abbr": "WA" },
                                                                        { "name": "West Virginia", "abbr": "WV" },
                                                                        { "name": "Wisconsin", "abbr": "WI" },
                                                                        { "name": "Wyoming", "abbr": "WY"}]
                    },
{ "name": "Canada", "abbr": "CA", "states": [{ "name": "Alberta", "abbr": "AB" },
                                                                    { "name": "British Columbia", "abbr": "BC" },
                                                                    { "name": "Manitoba", "abbr": "MB" },
                                                                    { "name": "New Brunswick", "abbr": "NB" },
                                                                    { "name": "Newfoundland and Labrador", "abbr": "NL" },
                                                                    { "name": "Northwest Territories", "abbr": "NT" },
                                                                    { "name": "Nova Scotia", "abbr": "NS" },
                                                                    { "name": "Nunavut", "abbr": "NU" },
                                                                    { "name": "Ontario", "abbr": "ON" },
                                                                    { "name": "Prince Edward Island", "abbr": "PE" },
                                                                    { "name": "Quebec", "abbr": "QC" },
                                                                    { "name": "Saskatchewan", "abbr": "SK" },
                                                                    { "name": "Yukon", "abbr": "YT"}]
},
{ "name": "Mexico", "abbr": "MX", "states": [
					      { "name": "Aguascalientes", "abbr": "AGS" },
		                  { "name": "Baja California Norte", "abbr": "BCN" },
						  { "name": "Baja California Sur", "abbr": "BCS" },
						  { "name": "Campeche", "abbr": "CAM" },
						  { "name": "Chiapas", "abbr": "CHIS" },
						  { "name": "Chihuahua", "abbr": "CHIH" },
						  { "name": "Coahuila", "abbr": "COAH" },
						  { "name": "Colima", "abbr": "COL" },
						  { "name": "Distrito Federal", "abbr": "DF" },
						  { "name": "Durango", "abbr": "DGO" },
						  { "name": "Guanajuato", "abbr": "GTO" },
						  { "name": "Guerrero", "abbr": "GRO" },
						  { "name": "Hidalgo", "abbr": "HGO" },
						  { "name": "Jalisco", "abbr": "JAL" },
						  { "name": "México - Estado de", "abbr": "EDM" },
						  { "name": "Michoacán", "abbr": "MICH" },
						  { "name": "Morelos", "abbr": "MOR" },
						  { "name": "Nayarit", "abbr": "NAY" },
						  { "name": "Nuevo León", "abbr": "NL" },
						  { "name": "Oaxaca", "abbr": "OAX" },
						  { "name": "Puebla", "abbr": "PUE" },
						  { "name": "Querétaro", "abbr": "QRO" },
						  { "name": "Quintana Roo", "abbr": "QROO" },
						  { "name": "San Luis Potosí", "abbr": "SLP" },
						  { "name": "Sinaloa", "abbr": "SIN" },
						  { "name": "Sonora", "abbr": "SON" },
						  { "name": "Tabasco", "abbr": "TAB" },
						  { "name": "Tamaulipas", "abbr": "TAMPS" },
						  { "name": "Tlaxcala", "abbr": "TLAX" },
						  { "name": "Veracruz", "abbr": "VER" },
						  { "name": "Yucatán", "abbr": "YUC" },
                          { "name": "Zacatecas", "abbr": "ZAC"}]
},
{ "name": "Other International", "abbr": "OINT", "states": [] }
];

Here’s what the configuration screen might look like:

2_Form Properties

1_Form Handler Properties

Here’s what the result looks like with states configured for the selected country:

Populated Country and State values in dropdown lists

3_Account Demographics

Country Dropdown list

4_Country Dropdownlist

State dropdown list
5_State Dropdownlist