Michael Jones -
Giga Sage

Every so often you need to control what options are available in a field based on the selection made in another field. I posted an article (here) that describes how to do this when your options are table-driven and you are using a lookup select box or list collector, but that isn't always an option. Sometimes you just need to create options that don't exist as records anywhere else. 

For those instances the methods involved are relatively simple to use, but can become cumbersome when you are dealing with anything other than a few variations; the code-blocks can easily grow out of control. As a result I wrote a function that simplifies the process, helps keep code to a minimum, and takes care of a lot of the housekeeping chores you otherwise have to remember each time. 

For this example we will use two select boxes, one with static values (drink_type) and one with dynamic values (drink_brands). 

The field drink_type has the values: -- None --, coffee, cola, energy.

When Coffee is selected, we want drink_brands to display labels for  -- None --, Starbucks, Folgers and Dunkin Donuts.

When Cola is selected, we want drink_brands to display -- None --, Coke, Pepsi, Jolt.

When Energy is selected, we want drink_brands to display -- None --, Monster, Rockstar, Venom.

Now we create an onChange script for drink_type.One special note, for this use-case I've modified the default code for the onChange so that if (isLoading || newValue = '') {  becomes if (isLoading) { so that if the user selects "-- None --", we still take action. 

Here is the script: 

function onChange(control, oldValue, newValue, isLoading) {
	if (isLoading) {
		return;
	}
	//start of with an empty set of values
	var values = '';
	
	//Define the values you want to conditionally create options for
	switch(newValue) {
		case "coffee":
		values = 'starbucks:Starbucks,folgers:Folgers,dunkin_donuts:Dunkin Donuts';
		break;
		
		case "cola":
		values = 'coke:Coke,pepsi:Pepsi,jolt:Jolt';
		break;
		
		case "energy":
		values = 'monster:Monster,rockstar:Rockstar,venom:Venom';
		break;
		
		default:
	}
	
	//Call the function to add the items to the field
	createDependentOptions('drink_brands', values, true);
	
}

function createDependentOptions(dependentField, dependentValues, includeNone) {
	//dependentField = name of the field you want to populate with options
	//dependentValues = a string in the format of value1:label1,value2:label2,value3,label3
	//includeNone set to true or false. true will result in -- None -- being added as a label with no value to position 0
	
	//Start by clearing the options
	g_form.clearOptions(dependentField);
	
	//If includeNone is true, add a label for none with a value of ''
	var index = 0;
	if(includeNone) {
		g_form.addOption(dependentField,'', '-- None --', 0);
		//If none was added, increment the index
		index++;
	}
	
	//Split dependentValues by comma into an array
	var arr = dependentValues.split(',');
	
	if(dependentValues != '') {
		for(var i = 0; i < arr.length; i++) {
			//For each member of the array, create the option value, label and index and add it to the field
			g_form.addOption(dependentField, arr[i].split(':')[0], arr[i].split(':')[1], i + index);
		}
	} 
}

The createDependentOptions function does all of the heavy lifting. You just define your switch cases and the list of options you want to display, decide if you want to include none, and it's done. In the string for values you pass the actual system value you want, separated with : followed by the label (display) you want to display. 

Although the example is simple, this method really comes into its own when you run into a situation where you might need to create a ton of options on the fly.

I've also used this method when I need to display items to a user where they might not normally have access to see particular records, but where you want to give them options to select from while still maintaining a reference to the records. For example, if you wanted to let users select a group to add a user to, but you don't want to give everyone access to view groups, you would use GlideAjax to query a list of groups and return a string formatted like sys_id:name1,sys_id:name2, etc. Then run that string through createDependentOptions to display a list of group names to the user, but the value would be the sys_id of the group so that you could, for instance, trigger a script to add the selected user to the selected group without an intermediate query. 

If you found this article helpful or useful, please be kind and click appropriately. If you found it really useful, you could always use the 3-dot menu to bookmark it for later! 

Michael Jones - Proud member of the Cloudpires team!

Comments
Jeff Wentworth
ServiceNow Employee
ServiceNow Employee

This was exactly what I was looking for to apply in my current project.

 

Have you put out a YouTube video since you published this?

 

Currently, I have created the two variables (i.e., select boxes in my case) and the catalog client script. I have based the catalog client script to trigger off the respective catalog item and initial/triggering select box. I have copied and pasted your script into the advanced/script field. I'm currently trying to identify how the script identifies/calls out to the second select box.

Mollie V
Tera Guru

Awesome, Michael. This is just what I was looking for and it works quite well.  However, I'd like to take this further and ask if it's possible to populate the case values from the list of values, like the question_choice values.

 

Have you done something similar?

 

Thanks!

jitendra-201233
Tera Contributor

Michael Jones

Good work, I need the same situation in my current project thank i will try to implement in my project.  

Version history
Last update:
‎01-23-2020 11:08 AM
Updated by: