Introduction
Microsoft introduced Multi Select Option Set in Dynamics 365 V9.0, which will help us to select more than one option.
Recently we had a business requirement, where the client required multi-select option set values to populate programmatically on selection of another multi-select option set.
To achieve this, first, we need to create two multi-select option set fields in CRM e.g. Mobile Company (Parent Multi-Select option set) and Mobile Handset (Child Multi-Select option set).
Then we need to create one JSON web resource in Dynamics 365 CRM, where we can define child option set values against each parent option set value.
JSON
E.g.
var JsonDataobj =
[{mobileCompany: 100000010,
mobileHandset: [
{value: 100000011,text: ‘Nokia 6.1’},
{value: 100000012,text: ‘Nokia 7.1’},
{value: 100000013,text: ‘Nokia 8.1’}
]},
{
mobileCompany: 100000020,
mobileHandset: [
{value: 100000021,text: ‘iPhone X’},
{value: 100000022,text: ‘iPhone 7’}
]},
{
mobileCompany: 100000030,
mobileHandset: [
{value: 100000031,text: ‘Samsung S8’}
]
}]
Now onLoad of Entity Form and onChange of parent Multi-Select option set we need to call below script.
Script
cascadingMultiOptionSet(executionContext): void {
/// <summary>
/// This function trigger on onload of form and onchange of Parent multi-option set field and set values of child multi option set field
/// </summary>
/// <returns type=”void” />
var functionName = “cascadingMultiOptionSet”;
var newChildOptArr = [];
var position = 0;
var newSelectedChildOpts = new Array();
try {
//JSON data retrieved from webresource
var parentChildCollection = JsonDataobj;
var formContext = executionContext.getFormContext();
//get parent’s selected option values
var selectedParentOptValue = formContext.getAttribute(“ikl_mobilecompanies”).getValue();
//check if value selected or not
if (selectedParentOptValue != null && selectedParentOptValue.length > 0) {
//add value from parentChildCollection array to newChildOptArr.
for (var i = 0; i < selectedParentOptValue.length; i++) {
newChildOptArr = newChildOptArr.concat((parentChildCollection.find(x => x.mobileCompany == selectedParentOptValue[i])).mobileHandset);
}
//get all options from child option set
var existingChildOptValues = formContext.getControl(“ikl_mobilehandset”).getOptions();
//get selected options from child optionset
var selectedChildOptValue = formContext.getAttribute(“ikl_mobilehandset”).getValue();
var childOptCount = existingChildOptValues.length;
//remove options from child optionset
for (var i = childOptCount – 1; i >= 0; i–) {
//check if option is not selected or not present in newChildOptArr array then remove that option
if (selectedChildOptValue == null || selectedChildOptValue.indexOf(parseInt(existingChildOptValues[i].value)) <= -1 || (newChildOptArr.find(x => x.value == existingChildOptValues[i].value)) == undefined) {
//remove options from child options set
formContext.getControl(“ikl_mobilehandset”).removeOption(existingChildOptValues[i].value);
}
}
//set position of new element
position = selectedChildOptValue == null ? 0 : selectedChildOptValue.length;
//clear selected values from child option set
formContext.getAttribute(“ikl_mobilehandset”).setValue(null);
//add new options from newChildOptArr to child option set field
for (var i = 0; i < newChildOptArr.length; i++) {
//if value aready selected then don’t add that value
if (selectedChildOptValue == null || selectedChildOptValue.indexOf(parseInt(newChildOptArr[i].value)) <= -1) {
//addOptions with values and position
var optionSet = new Object();
optionSet.value = newChildOptArr[i].value;
optionSet.text = newChildOptArr[i].text;
formContext.getControl(“ikl_mobilehandset”).addOption(optionSet, position++);
}
//add previously selected option set to newSelectedChildOpts array
if (selectedChildOptValue != null && selectedChildOptValue.indexOf(parseInt(newChildOptArr[i].value)) > -1) {
newSelectedChildOpts = newSelectedChildOpts.concat(parseInt(newChildOptArr[i].value, 10));
}
}
}
else//if parent options not selected then clear child options
{
formContext.getAttribute(“ikl_mobilehandset”).setValue(null);
formContext.getControl(“ikl_mobilehandset”).clearOptions();
}
//set value of selected child option set
if (newSelectedChildOpts != null && newSelectedChildOpts.length > 0) {
formContext.getAttribute(“ikl_mobilehandset”).setValue(newSelectedChildOpts);
}
}
catch (ex) {
throw new Error(ex);
}
}
Result
1) If we select Nokia in Mobile Company Multi-select option set, then the Mobile Handset will bind only mobile handsets of Nokia.
2) If we select Apple and Nokia in Mobile Company, then both Apple and Nokia handset will be displayed in Mobile Handsets multi-select option set and the selected values of Nokia will remain the same.
3) If we remove Nokia from Mobile Company, then only Apple company handsets will be displayed in Mobile Handset multi-select option set and the selected options of Nokia handset will be cleared.
4) If the Mobile Company doesn’t contain any value, then Mobile Handset multi-select option will remain empty.
In order to see saved values of the multi-select option set for both parent and child it is necessary to trigger the above script function on a load of form.
Conclusion
We can achieve cascading of two multi-select option set from the above given script.
This code is not working on IE.
IE does not support “=>”, JS is not loaded.
Can you please guide me
Yes, IE 11 does not support use of Arrow functions. Instead, it uses regular ‘functions’ as given below:
Replace:
var newChildOptArr = newChildOptArr.concat((parentChildCollection.find(x => x.mobileCompany == selectedParentOptValue[i])).mobileHandset);
With this:
var newChildOptArr = newChildOptArr.concat(parentChildCollection.find(function (x) {return x.mobileCompany == selectedParentOptValue[i];}).mobileHandset);
and,
Replace:
(newChildOptArr.find(x => x.value == existingChildOptValues[i].value)) == undefined)
With this:
(newChildOptArr.find(function (x) {return x.value == existingChildOptValues[i].value;})==undefined)
Hope this helps.
Thanks!