Introduction
This article explains how to implement a UI policy to toggle the disabled/mandatory states of two fields based on their values.
The goal is to control the accessibility and mandatory setting of two fields, based on their values, such as if the first field is set, then the other field becomes disabled and vice-versa.
There could be various way to implement this, and this article proposes to do it with a UI policy.
For instance, let’s say we have two fields: Company and Person. The user must populate either one of these fields, as shown in this recording:
Implementation
To achieve this, we can create a UI policy named “Toggle disabled state of Company and Person” on the table.
Conditions
In the conditions, you need to checks whether either field contains any value, by using “Company Is Anything or Person is Anything” (companyANYTHING^ORpersonANYTHING^EQ
).
Scripts
Then, in the Script tab, set “Run scripts” and enter the two scripts like in the examples below.
When the Condition is True
The condition evaluates to true when at least one of the fields (“company” or “person”) contains a value.
The script then disables the field that does not have a value while leaving the field with a value enabled.
This ensures that users input data into only one of these fields.
If by any chance both fields contain values, neither of them is disabled, allowing the user to retain or modify the existing data in both fields.
function onCondition() {
/*
The condition is true when at least one of the two fields has a value set.
In this case, we disable the other field, except for the case where both fields are set.
*/
// Names of the fields
let companyField = "company";
let personField = "person";
// Get the value of the fields
let companyValue = g_form.getValue(companyField);
let personValue = g_form.getValue(personField);
// If both values are set (e.g., set from the list), return as we don't want to disable any of them.
if (companyValue && personValue) {
return;
}
// If the company is set, disable the person field
if (companyValue) {
g_form.setMandatory(personField, false);
g_form.setDisabled(personField, true);
}
// If the person is set, disable the company field
if (personValue) {
g_form.setMandatory(companyField, false);
g_form.setDisabled(companyField, true);
}
}
When the Condition is False
The condition becomes false when neither the “company” nor “person” fields have values set.
The script then enables both fields, making them available for user to input data, and sets them as mandatory.
The user is required to populate at least one of these fields for the form.
function onCondition() {
/*
The condition is false when both fields are not set.
In this case, we enable both fields as they are open for input.
*/
// Names of the fields
let companyField = "company";
let personField = "person";
// Get the value of the fields
let companyValue = g_form.getValue(companyField);
let personValue = g_form.getValue(personField);
// If the company field is not set, enable the person field
if (!companyValue) {
g_form.setMandatory(personField, true);
g_form.setDisabled(personField, false);
}
// If the person field is not set, enable the company field
if (!personValue) {
g_form.setMandatory(companyField, true);
g_form.setDisabled(companyField, false);
}
}
What does the ISANYTHING operator do ?
Now you are maybe wondering what is the ISANYTHING operator that we are using the UI policy.
According to ServiceNow documentation[^1], it means that it matches on the following values: any value, empty, null.
Also in the KB article KB0815207[^2], it says:
By design, the “is anything” filter operator always evaluates to true whether a field is empty or not."
But is this really true ?
The explanations above were all I could find in the documentation (admittedly I didn’t look much more). But then, if it is always true, why do we need a script for the false condition ?
To be sure, I made a test by displaying a message in each script, so to know which one is executed when, like this:
// Test execution
let msg = `condition TRUE\ncompanyField=${companyValue} (${companyValue==null}/${companyValue==""})\npersonValue=${personValue} (${personValue==null}/${personValue==""})`;
alert(msg);
You can see the result here:
So we can see that:
- when loading the empty form, it evaluates to false
- when entering a value in one of the field, it evaluates to true
- when emptying the field, it evaluates to false
So we can observe that it doesn’t really behave like it is suggested in the documentation.
But fortunately we can circumvent this discrepancies by using both the true and false script and achieve what we aimed for.
Despite of having two scripts, the UI policy solution is in my opinion more elegant than using Client Script. Using Client Script would require to have a script for each field and duplicate the code in different places. The UI policy allows to keep everything tidy in one place.