Michael Jones -
Giga Sage

Every so often the question comes up "How can I make one drop down dependent on the value in another?" and, while there are several ways to accomplish this, the easiest one is using a feature built into the platform. 

For this process to work the values that you want to populate in both fields should be drawn from a table (can be different tables as long as there is a value to key on) with both variables being Lookup Select Boxes. In this example we'll use the cmn_location table. 

Setup your first Lookup Select Box so that the values displayed are the ones you want the user to be able to select from.

For the example we'll name our first variable state and configure the Lookup Select Box to lookup values form the cmn_location table, from the field "State / Province". We'll include the option for none and select unique values only. 

For the second Lookup Select Box (call it country) we will also lookup values from the cmn_location table, from the field "Country". We won't include none for this field, but we will select unique values again. In addition, we will need to set a reference qualifer on the field (same tab as the type specifications)

javascript: 'state='+current.variables.state

We then need to add a variable attribute (same tab as default value) which would look like this: 

ref_qual_elements=state

When you load the item and select a state, the value displayed in country will automatically be updated to reflect the country associated with the selected state. 

What makes this possible is in part the reference qualifier, which is written to reference the current value of the state field (but, if you notice, this is written in server-side, not client-side javascript).

The second things that makes this possible is the variable attribute that we configured - ref_qual_elements=state. This attribute is a flag that tells the platform to monitor the field you name for changes and, if detected, re-evaluate the reference qualifier and displayed values server-side.

Note, this same process can be applied to Lookup multiple choice and List Collector type fields as well as Lookup select box. You are also not limited to only one dependent field. You can specify multiple fields to watch in ref_qual_elements by separating variable names with  a semi-colon such as state;country;street

If you found this article helpful, please be kind and remember to click appropriately. If you found it really helpful, maybe bookmark it for later reference. 

Comments
Randall Arnold
Giga Expert

Very helpful, thanks.

I have a similar need to create a relationship between 2 catalog variables.  Is there a way to change the value of a Text box based on a Select box dropdown change in the same cart?

Michael Jones -
Giga Sage

There are certainly some methods you could use, depending on the details of your setup and what you have available. If your select box is populated from a table, and the table contains the text you want to populate in the text box as well as the choice option, then you could create an onChange that calls a GlideAjax to find the value and in the callback set it. 

If the select box values are just hard-coded then could still do it via a client-script on change, but you would have to script out each combination (newValue of select box and value you want in the text field) and use a switch case to set it. 

If you want to provide more details, I'd be happy to help you figure it out.

Randall Arnold
Giga Expert

Perfect!  My values are hard-coded and I already have the switch--it's just in a Request Item workflow and already handling the auto-assignment after my Inbound Action runs.  I just needed it to also work on the manual side in the service catalog, and you lead me to suspect it's all about *moving* my switch to handle the cart update (regardless of whether it's from IA or manual).  That was my original thought but couldn't find out how (ServiceNow's dead-end docs are frustrating for me).

I just need to figure out the details... I've been stymied by client scripts so far...

Randall Arnold
Giga Expert

got started on this.  Here's my client code:

function onChange(control, oldValue, newValue, isLoading) {
   if (isLoading || newValue == '') {
      return;
   }

   //Type appropriate comment here, and begin script below
   
   //Type appropriate comment here, and begin script below
    var systemProcessingGroup = g_form.getReference('system', doAlert);
}

function doAlert(systemProcessingGroup){

//assignment group matrix for Request Item (and Request)
//note: toString() is necessary for Switch blocks!

switch (systemProcessingGroup.toString()) {
    case "AD Global Group":
    case "AS400":
    case "Contractor Validations":
    case "SOX Databases":
        current.assignment_group = "01635186db56e3807137ab8b4b961960";
        // ID-Management
        break;
    case "Hyperion":
        current.assignment_group = "0d635186db56e3807137ab8b4b961955";
        // Hyperion Applications Support
        break;
    case "FIS":
        current.assignment_group = "ac631186db56e3807137ab8b4b96193d";
        // FIS Support Level 2 (AS/400 Admin & Rental Apps)
        break;
    case "Mainframe":
    case "Walker":
    case "Mainframe – QQQ IDs":
        current.assignment_group = "1b75b2d6db9833c09e9bf2713996192e";
        // RACF Security
        break;
    case "SAP":
        current.assignment_group = "6d639186db56e3807137ab8b4b96191a";
        // SAP Admin
        break;
    default:
        // switch failed; no identified assignment group
}

//update Summary variable:

g_form.setValue('summary', "Access Audit Request for " + current.assignment_group.getDisplayValue());

 

of course, I'm getting an error for using current... I just need to find out how to access the current Request Item from the client script...

Michael Jones -
Giga Sage

Maybe I misunderstood (sorry, reading too fast)

When you say "cart" do you mean a scenario where you have already "added some items to the cart" moved on to a different Catalog Item, and you want to update values for all of the items in the Cart, based on a change you just made in an item you've not added yet?

If so, it is a little tricky, but it can be done. You have to "combine" client-scripting and server-side scripting by using a client script to detect the change and then call a GlideAjax script include, passing the information server-side to process the update. 

You would want to pass the name of the variable and the value you want to set and then, inside your GlideAjax, you would use a method something like this to iterate through the cart items, find your variable and update the value. 

The Script Include would look something like this

Name updateCart

Client-Callable = checked. 

 

var updateCart = Class.create();
updateCart.prototype = Object.extendsObject(AbstractAjaxProcessor, {
	
	updateCart: function() {
		var fieldName = this.getParameter('sysparm_fieldName');
		var fieldValue = this.getParameter('sysparm_fieldValue');
		//Get the Cart
		var sc = new GlideRecord('sc_cart');
		sc.addQuery('user', gs.getUserID());
		sc.query();
		while(sc.next()){
			//Check each item
			var item = new GlideRecord('sc_cart_item');
			item.addQuery('cart', sc.sys_id);
			item.query();
			while(item.next()){
				//Check each variable
				var option = new GlideRecord('sc_item_option');
				option.addQuery('cart_item', item.sys_id);
				option.query();
				while(option.next()) {
					//If the variable is named hardware_type
					if(option.item_option_new.name == fieldName) {
						//set the value to be keyboard
						option.value.setValue(fieldValue);
						option.setWorkflow(false);
						option.update();
					}
				}
				
			}
		}
		
	},
	type: 'updateCart'
	
});

 

Then say for example you have a field in your items named "hardware_type" and you want to set the value in all of the items to "Business and Personal Use" based on a change in a selectbox, you would then call this in the client: 

   var aj = new GlideAjax('updateCart');
   aj.addParam('sysparm_name', 'updateCart');
   aj.addParam('sysparm_fieldName', 'hardware_type');
   aj.addParam('sysparm_fieldValue', 'Business and Personal Use');
   aj.getXML(); //You don't need a callback as you don't need to return anything to the client

 

That should get you moving in the right direction! 

Michael Jones -
Giga Sage

Ah! Ok, so I was sort of wrong again - what you are after is:

User makes a selection in a Select Box then, based on the value, you want to set the assignment_group on the RITM when it is submitted?

The easiest way to do that would be to create a Business Rule on the sc_req_item table, advanced, before, insert, with a condition of "Item is <your item>" then, in the script: 

 

(function executeRule(current, previous /*null when async*/) {
	// Add your code here
	
	var systemProcessingGroup = current.variables.system.getDisplayValue();
	
switch (systemProcessingGroup) {
    case "AD Global Group":
    case "AS400":
    case "Contractor Validations":
    case "SOX Databases":
        current.assignment_group = "01635186db56e3807137ab8b4b961960";
        // ID-Management
        break;
    case "Hyperion":
        current.assignment_group = "0d635186db56e3807137ab8b4b961955";
        // Hyperion Applications Support
        break;
    case "FIS":
        current.assignment_group = "ac631186db56e3807137ab8b4b96193d";
        // FIS Support Level 2 (AS/400 Admin & Rental Apps)
        break;
    case "Mainframe":
    case "Walker":
    case "Mainframe – QQQ IDs":
        current.assignment_group = "1b75b2d6db9833c09e9bf2713996192e";
        // RACF Security
        break;
    case "SAP":
        current.assignment_group = "6d639186db56e3807137ab8b4b96191a";
        // SAP Admin
        break;
    default:
        // switch failed; no identified assignment group
}

//update Summary variable:

current.variables.summary = "Access Audit Request for " + current.assignment_group.getDisplayValue();
	
	
})(current, previous);

 

It would update the RITM just before it is inserted, based on the value selected (if I followed the way you were checking the value correctly. Short versions is, when current is an sc_req_item you can access any variable value with current.variables.<name> and if that variable is a reference, you can do walk to referenced values, etc. 

 

Hope that helps!

Randall Arnold
Giga Expert

For now I decided to keep the operations separate, but I may look at using your approach for an update, thanks.

Here's my final code just for updating the cart summary variable with the assigned group name, and it works!  You and a colleague were a huge help.

function onChange(control, oldValue, newValue, isLoading) {
    if (isLoading || newValue == '') {
        return;
    }

    //begin script below
    var systemProcessingGroup = g_form.getValue('system');

    //assignment group matrix for Request Item (and Request)
    //note: toString() is necessary for Switch blocks!
    var si = "";
    switch (systemProcessingGroup.toString()) {
        case "AD Global Group":
        case "AS400":
        case "Contractor Validations":
        case "SOX Databases":
            si = "01635186db56e3807137ab8b4b961960";
            // ID-Management
            break;
        case "Hyperion":
            si = "0d635186db56e3807137ab8b4b961955";
            // Hyperion Applications Support
            break;
        case "FIS":
            si = "ac631186db56e3807137ab8b4b96193d";
            // FIS Support Level 2 (AS/400 Admin & Rental Apps)
            break;
        case "Mainframe":
        case "Walker":
        case "Mainframe – QQQ IDs":
            si = "1b75b2d6db9833c09e9bf2713996192e";
            // RACF Security
            break;
        case "SAP":
            si = "6d639186db56e3807137ab8b4b96191a";
            // SAP Admin
            break;
        default:
            // switch failed; no identified assignment group
    }

    //update Summary variable:
    var gr = new GlideRecord('sys_user_group');
    gr.addQuery('sys_id', si);
    gr.query();
    if (gr.next()) {
        g_form.setValue('summary', 'Access Audit Request for ' + gr.name);
    }
}

Katrina3
Mega Explorer

Hi there! Did you ever get an answer to your question? I have a similar issue. 

Thanks! 

Randall Arnold
Giga Expert

yes; the solution (for me) is in my reply above

Katrina3
Mega Explorer

Thanks!

AndyLock
Mega Guru

Hi Randall,

Can you configure System Policy => Assignment Rules or System Policy => Assignment for your needs, rather than migrate away from OOB?

Community Alums
Not applicable

Exactly what I was looking for.
Thanks Michael!!!

V_31
Tera Expert

Hi Michael,

Hoping you can help. I am trying to achieve the above but have created a custom table so that the dependency can be maintained over time rather than using a script.

The table created extends the location table as information is required from location. I have also created a field called "Site type" within the location table and use it within my custom table. Depending on what "Site type" is on the custom table, the relevant options should be available for "endpoint devices" field" (created on custom table).

To get this to work front end i followed your instructions but cannot see the options available. See screenshots below.

 

Site type variable select box

find_real_file.png

Endpoint devices lookup select box

find_real_file.png

Ryax1
Tera Guru

Brilliant article that was very easy to follow and gave me exactly what I needed. Thanks so much!

Rich

Jeffrey Barton
Tera Contributor

I'm on tokyo and this doesn't seem to be working for me. Sorry for the shadow post a year later but I need this to work.  I have a custom table and I went so far as to call the variables by state and country but with my Question.  Does anyone know if this broke in tokyo?

suuriya
Tera Contributor

Hi @Jeffrey Barton ,

 

Did you get the solution for this..even I face same in Tokyo

 

Jeffrey Barton
Tera Contributor

Yes,

It's not broken in tokyo.  The key was in the reference qualifier. 

I had to manually figure out how to setup the proper JavaScript. Thankfully I had a friend who had done this before and was well aware of how to do it.  

my example is this:
javascript&colon; 'u_access_department='+current.variables.pega_department

First one is the field you're checking and the second is the field you're filling in.

I hope that helps.

 

Version history
Last update:
‎01-20-2020 05:23 PM
Updated by: