New Dependent Picklist Sample

People frequently need to use client scripts to create dependent drop-down (picklist) fields.

We have had a “Dynamic Picklist” sample in the SDK for some time, but I received feedback that it didn’t work so well. The effort to fix that sample evolved into creating an entirely new sample. Look for it under \sdk\client\fullsample\dependentpicklist. The old “Dynamic Picklist” sample has been retired.

In addition to fixing the problems with the existing sample, this new “Dependent Picklist” sample provides more features and illustrates a best practice for defining functions within form event code.

Features

Supports defining more than two dependent picklists. This allows you to chain together a number of picklist fields to increasingly more specific set of options.

image

Option mappings are defined in a separate section. Once you define how each field and each option is mapped to a parent option, you don’t need to make any changes to the code that does the filtering of options. These options are mapped using an array of objects defined using literal notation. This style of defining objects in an array is intended to make the mapping easier to read and edit.

   1: /* Map the dependencies START*/

   2:  /*

   3:  This sample maps 2 dependent picklists for this form. 

   4:    * new_category > new_subcategory

   5:    * new_subcategory > new_type

   6:  */

   7:  var gArrDependentPicklists =

   8:   [{

   9:  "ParentFieldId": "new_category",

  10:  "ChildFieldId": "new_subcategory",

  11:    "ChildFieldLabel": "Sub-Category",

  12:    "OptionsGroup":

  13:     [

  14:      {"ParentValue": "1",

  15:       "ChildOptionValues": ["", "1", "2", "3"]

  16:      },

  17:      {"ParentValue": "2",

  18:       "ChildOptionValues": ["", "4", "5", "6", "7", "8"]

  19:      }

  20:     ]

  21:    },

  22:    {

  23:    "ParentFieldId": "new_subcategory",

  24:    "ChildFieldId": "new_type",

  25:    "ChildFieldLabel": "Type",

  26:    "OptionsGroup":

  27:     [

  28:      {"ParentValue": "1",

  29:       "ChildOptionValues": ["", "1", "2", "3", "4"]

  30:      },

  31:      { "ParentValue": "2",

  32:        "ChildOptionValues": ["", "5", "6", "7"]

  33:      },

  34:      {"ParentValue": "3",

  35:       "ChildOptionValues": ["", "8", "9", "10", "11"]

  36:      },

  37:      {"ParentValue": "4",

  38:       "ChildOptionValues": ["", "12", "13", "14", "15"]

  39:      },

  40:      {"ParentValue": "5",

  41:       "ChildOptionValues": ["", "16", "17", "18", "19"]

  42:      },

  43:      {"ParentValue": "6",

  44:       "ChildOptionValues": ["", "20", "21", "22", "23"]

  45:      },

  46:      {"ParentValue": "7",

  47:       "ChildOptionValues": ["", "24", "25", "26", "27"]

  48:      },

  49:      {"ParentValue": "8",

  50:       "ChildOptionValues": ["", "28", "29", "30"]

  51:      }

  52:     ]

  53:    }

  54:   ];

  55: /* Map the dependencies END*/

Provides a warning when the script is not synchronized with the options. Any script that creates dependent picklist options can be broken when new options are added. It would be very easy for someone to add a new options and not immediately notice that the script is affected. This script compares the number of options against the number of options that are mapped. If the number is different, an alert message will provide details alerting the customizer that the script is out of sync with the current options.

image

More resilient. Many of the dependent picklist samples you may find when searching the internet can rely on sets of contiguous options or may actually depend on the text labels provided for each option. This can cause the script to break if someone sorts the way the options are presented or if you are using a localized user interface. This sample shows how to avoid those problems.

Defining reusable objects within the Onload event of a form

When you look at the client side JScript samples provided before now in the CRM SDK you may notice that none of the samples include the definition of an object (or a function – a type of object) that might be re-used in another event, such as OnChange or OnSave. Although this is a common (some would say essential) practice it poses some problems for upgradability. Which object in the DOM should you attach your objects or functions to? Many people attach them to the CrmForm object. What happens if you define a function to CrmForm that has the same name as one of the functions provided by Microsoft CRM? There is a risk that the CRM function will be overwritten, potentially breaking some CRM functionality. What if CRM introduces a new function with the same name as one you have defined? Same result.

This sample introduces the best practice of attaching objects to the window object through an arbitrary ‘namespace’ object. This should minimize the risk of overwriting objects in the DOM.

For example, this sample requires that code in an Onchange event can access the filterChildField function defined in the OnLoad event. To make this available it is attached to a crmSDKSample object which is then attached the window object.

//Create an arbitrary object to serve as a namespace

var crmSDKSample = new Object();

/*Attach the global dependancy array to the crmSdkSample object */

crmSDKSample.gArrDependentPicklists = gArrDependentPicklists;

/*Attach the function to the crmSDKSample*/

crmSDKSample.filterChildField = filterChildFieldFunction;

/*Attach the crmSDKSample to the window so it is globally available*/

window.crmSDKSample = crmSDKSample;

To call the function from the onChange event, the syntax looks like this:

crmSDKSample.filterChildField("new_category", "new_subcategory");

Because the window object is one part of the DOM that is almost certain to exist in future versions of CRM forms – this object is more likely to continue to be available after an upgrade.

Sample Code

As always, the sample code provided in the SDK are not intended to be used in a production environment without prior testing. You should deploy this sample to a test environment and examine it for interaction or interference with other parts of the system.

I hope this sample provides you with some insights into creating dependent picklists as well as ideas about defining reusable objects within client script.