logo

NJP

How to control the available choices of a choice list in a ServiceNow form

Import · Mar 15, 2013 · article

Setting the context

For a practical illustration, we will be controlling the list of available choices of the State field of an incident.In the out of the box installation of ServiceNow (for example on demo.service-now.com), an Incident can have the following states:

image

We will be controlling the list of choices for the incident state as per the following state diagram:

As per the diagram, we can only move into the Active state either from the New state or if the incident is just being created.

Step 1: creating a states transition table

In order to make the solution as dynamic as possible we create a new table in ServiceNow named incident_state_matrix having two columns (source_state, destination_state).This table has two choice fields 'Source State' and 'Destination State' that allow inserting valid transitions. These fields are choice lists that are are based on the incident states from the Incident [incident] table as per the screenshot below.

image

In this table we insert rows that represent the allowed transitions in the above diagram. Below is a screenshot of the populated table:

image

Step 2: Business rule that propagates the allowed states of an incident to the client browser

Create the following business rule:

Name: Allowed Incident States

Table: Incident

When: display

Active: trueIn the script section paste the following:

getAllowedStates();function getAllowedStates() { var current_state = current.state; var ismgr = new GlideRecord('u_incident_states_matrix'); ismgr.addQuery('u_source_state', current_state); ismgr.query(); var allowed_states = []; var index = 0; while (ismgr.next()) { allowed_states[index++] = ismgr.u_destination_state.toString(); } g_scratchpad.allowed_states = allowed_states;}

What is the above business rule does is generate an array of allowable states that is sends to the client browser as a scratchpad object.A client script on the client side will have to process the propagated array and control the list of selectable choices.

Step 3: Create a helper UI Script that facilitates enabling/disabling choice list options

Note: this script is inspired from a post that appeared on the SNCGuru blog at http://www.servicenowguru.com/scripting/client-scripts-scripting/removing-disabling-choice-list-options/Create the following UI Script:

Name: DisableEnableOptions

Active: true

Global: truePaste the following script:

function disableAllOptions(fieldName) { fieldName = g_form.removeCurrentPrefix(fieldName); var control = g_form.getControl(fieldName); if (control && !control.options) { var name = 'sys_select.' + this.tableName + '.' + fieldName; control = gel(name); } if (!control) return; if (!control.options) return; var options = control.options; for (var i = 0; i < options.length; i++) { var option = options; control.options.disabled = 'true'; }}function disableOption(fieldName, choiceValue) { fieldName = g_form.removeCurrentPrefix(fieldName); var control = g_form.getControl(fieldName); if (control && !control.options) { var name = 'sys_select.' + this.tableName + '.' + fieldName; control = gel(name); } if (!control) return; if (!control.options) return; var options = control.options; for (var i = 0; i < options.length; i++) { var option = options; if (option.value == choiceValue) { control.options.disabled = 'true'; break; } }}function enableOption(fieldName, choiceValue) { fieldName = g_form.removeCurrentPrefix(fieldName); var control = g_form.getControl(fieldName); if (control && !control.options) { var name = 'sys_select.' + this.tableName + '.' + fieldName; control = gel(name); } if (!control) return; if (!control.options) return; var options = control.options; for (var i = 0; i < options.length; i++) { var option = options; if (option.value == choiceValue) { control.options.disabled = ''; break; } }}

Step 4: Client script that controls the list of choices

Create the following client script:

Name: Allowed Incident States

Active: true

Global: true

Type: onLoad

Table: IncidentIn the script section paste the following:

function onLoad() { try { var current_state = g_form.getValue('state'); disableAllOptions('state'); enableOption('state', current_state); var allowed_states = g_scratchpad.allowed_states; var nb_states = allowed_states.length; for (var index = 0; index < nb_states; index++) { enableOption('state', allowed_states[index]); } } catch (err) { jslog(err.message); }}

Step 5: Business rule that checks if a state is allowed before saving a record

Create the following business rule:

Name: Check If Incident State Allowed

Table: Incident

Active: true

When: before

Insert: true

Update: truePaste the following script:

checkIfStateAllowed();function checkIfStateAllowed() { var bad_state = true; //If the record is being inserted then previous.state is nullvar previous_state = previous.state.toString() == 0 ? 1 : previous.state.toString(); var current_state = current.state.toString(); if (previous_state != current_state) { var ismgr = new GlideRecord('u_incident_states_matrix'); ismgr.addQuery('u_source_state', previous_state); ismgr.query(); while (ismgr.next()) { if (current_state == ismgr.u_destination_state.toString()) { bad_state = false; break; } } if (bad_state == true) { //If current.state did not match any destination state then we have to abort gs.addErrorMessage('Incident State Not Allowed'); current.setAbortAction(true); } }}

Testing

To test the solution create a new incident as per the below screenshot:

image

On the form you will notice that only the New and Active states are available:

image

If we set the incident state to Active and save the form then the list of available choices changes:

image

I hope this blog post has been useful for you.

Toni Soueid

Technical Consultant

ServiceNow

France

View original source

https://www.servicenow.com/community/in-other-news/how-to-control-the-available-choices-of-a-choice-list-in-a/ba-p/2276109