Top 10 ServiceNow Client Script Scenarios: Mastering Form Interactions
In the dynamic world of ServiceNow, delivering a seamless and intuitive user experience is paramount. This is where client scripts and UI policies shine, allowing us to tailor form behavior directly in the user’s browser. While ServiceNow offers a robust platform out-of-the-box, real-world business requirements often demand custom logic to enhance efficiency and enforce data integrity. This article dives into ten common and impactful scenarios where client scripts become indispensable. We’ll explore practical examples, understand the underlying concepts, and equip you with the knowledge to tackle these challenges effectively.
Whether you’re a seasoned ServiceNow developer or just starting your journey, mastering these scenarios will significantly boost your ability to build sophisticated and user-friendly applications. Let’s explore how to make your forms smarter!
Understanding the Core Concepts: Client Scripts vs. UI Policies
Before we jump into specific scenarios, it’s crucial to briefly touch upon the tools we’ll be using. Both Client Scripts and UI Policies operate on the client-side (in the user’s browser) to control form behavior. While they often achieve similar outcomes, they have distinct strengths:
- UI Policies: Generally preferred for simpler, declarative tasks like making fields mandatory, read-only, visible/hidden, or setting default values. They are easier to configure without extensive scripting and are often more performant. UI Policies also have a “Reverse if false” option, which is incredibly useful.
- Client Scripts: Offer greater flexibility and power. They are ideal for complex logic, calculations, interacting with other records, or when you need fine-grained control over form events.
Key takeaway: For straightforward visibility or mandatory/read-only changes, lean towards UI Policies. For anything more complex, or when you need to execute custom JavaScript logic, Client Scripts are your go-to. You can even use scripts within UI Policies if needed (Scenario 10).
Top 10 ServiceNow Client Script Scenarios
1. Dynamically Setting Field Values Based on Other Fields
This is a fundamental requirement. Imagine you have a ‘Category’ field and a ‘Subcategory’ field. When a user selects ‘Hardware’ for Category, you want to pre-populate Subcategory with ‘Laptop’ or ‘Desktop’. Or, perhaps you need to calculate a ‘Total Cost’ by summing up ‘Quantity’ and ‘Unit Price’. This scenario hinges on reacting to changes in one field to update another.
How it Works:
We use an onChange Client Script. This script triggers whenever a specific field’s value changes. Inside the script, we retrieve the new value of the trigger field and then use the g_form.setValue() method to update another field.
Example: Setting Subcategory based on Category
On the Incident form, let’s say we want to set a default Subcategory when the Category is ‘Request’.
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if (isLoading || newValue === '') {
return;
}
// Get the selected Category value
var category = newValue;
// Logic to set Subcategory based on Category
if (category === 'Request') {
g_form.setValue('subcategory', 'Standard'); // Assuming 'Standard' is a valid subcategory choice
} else {
g_form.setValue('subcategory', ''); // Clear subcategory if category changes to something else
}
}
Troubleshooting:
- Field Not Updating: Double-check the field names (API names) in
g_form.setValue('field_name', value). They must be exact. - No Script Triggering: Ensure the
onChangescript is attached to the correct field and that the ‘Onload’ checkbox is checked for it to run when the form initially loads. - Incorrect Value Being Set: Verify that the `newValue` correctly represents the value you expect from the triggering field. Use `g_form.log()` for debugging.
2. Making Fields Mandatory Based on Conditions
Often, a field only becomes mandatory under specific circumstances. For instance, if the ‘State’ of an incident is set to ‘Resolved’, the ‘Resolution Notes’ field must be filled. This ensures critical information is captured when it’s most relevant.
How it Works:
You can achieve this using either UI Policies or Client Scripts. For simpler, conditional mandatory requirements, UI Policies are often the cleaner approach. However, if the condition involves complex calculations or logic that’s easier to script, an onChange Client Script can be used to dynamically set the mandatory status.
Example: Mandatory Resolution Notes when State is Resolved (using UI Policy)
Create a UI Policy with the following configuration:
- Table: Incident
- Short description: Make Resolution Notes Mandatory when Resolved
- Condition: State IS Resolved
- Order: (e.g., 100)
- Onload: Checked
- Reverse if false: Checked
Then, create a UI Policy Action:
- Field: Resolution Notes
- Mandatory: True
Example: Mandatory Resolution Notes when State is Resolved (using Client Script)
This would involve an onChange script on the ‘State’ field.
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if (isLoading || newValue === '') {
return;
}
var state = newValue;
if (state === '7') { // Assuming '7' is the sys_id or value for 'Resolved' state
g_form.setMandatory('work_notes', true); // Or 'resolution_notes' if that's your field
} else {
g_form.setMandatory('work_notes', false);
}
}
3. Making Fields Read-Only Based on Conditions
Similar to mandatory fields, some fields might need to be read-only under certain conditions. For example, once an incident is ‘Closed’, fields like ‘Short description’ or ‘Description’ should not be editable.
How it Works:
Again, UI Policies are excellent for this. You define the condition under which the field becomes read-only, and the UI Policy handles the toggling. Client scripts can also achieve this using g_form.setReadOnly('field_name', true/false).
Example: Read-Only Fields when Incident is Closed (using UI Policy)
- Table: Incident
- Short description: Make fields read-only when Closed
- Condition: State IS Closed
- Onload: Checked
- Reverse if false: Checked
UI Policy Actions:
- Field: Short description, Mandatory: False, Read only: True
- Field: Description, Mandatory: False, Read only: True
Example: Read-Only Fields when Incident is Closed (using Client Script)
An onChange script on the ‘State’ field.
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if (isLoading || newValue === '') {
return;
}
var state = newValue;
if (state === '3') { // Assuming '3' is the value for 'Closed' state
g_form.setReadOnly('short_description', true);
g_form.setReadOnly('description', true);
} else {
g_form.setReadOnly('short_description', false);
g_form.setReadOnly('description', false);
}
}
4. Displaying or Hiding Fields Based on Conditions
User interfaces become cluttered when irrelevant fields are shown. This scenario focuses on conditional visibility: showing a ‘Cause’ field only when an incident is resolved or closed, or displaying a ‘Business Justification’ field only when a change request has a ‘Risk’ of ‘High’.
How it Works:
UI Policies are perfectly suited for this. You define the condition and then specify which fields should be visible or hidden.
Example: Show ‘Close Code’ and ‘Close Notes’ only when State is Closed (UI Policy)
- Table: Incident
- Short description: Show Close Fields when Closed
- Condition: State IS Closed
- Onload: Checked
- Reverse if false: Checked
UI Policy Actions:
- Field: Close Code, Visible: True
- Field: Close Notes, Visible: True
Note: If you need to show/hide fields based on complex scripting logic that can’t be easily defined in a UI Policy condition, you would use an onChange client script with g_form.setVisible('field_name', true/false).
5. Validating Field Values Before Form Submission (Client-Side)
This is crucial for data integrity and user experience. Instead of letting users save data that’s clearly incorrect and then flagging it server-side, we can catch errors early. Examples include ensuring a ‘Due Date’ is not before the ‘Open Date’ or that a numerical field doesn’t exceed a certain limit.
How it Works:
onSubmit Client Scripts are used for this. These scripts run just before the form data is submitted to the server. If the script returns false, the submission is cancelled, and an error message can be displayed.
Example: Ensure Due Date is after Open Date
On a Task table form (like Incident or Request Item).
function onSubmit() {
var openDate = g_form.getValue('opened_at');
var dueDate = g_form.getValue('due_date');
if (openDate && dueDate) { // Check if both fields have values
var openedAt = new Date(openDate);
var dueDateObj = new Date(dueDate);
if (dueDateObj < openedAt) {
alert('Due Date cannot be before the Open Date.');
return false; // Prevents form submission
}
}
return true; // Allows form submission
}
6. Getting Current User Information (Client-Side)
Frequently, you need to know who is currently logged in to perform specific actions. For example, to pre-populate an ‘Assigned To’ field with the current user or to check if the user is part of a specific group before allowing an action.
How it Works:
ServiceNow provides the g_user object for client-side access to user information.
Example: Get Current User’s Name and System ID
// Get the current logged-in user's display name
var currentUserDisplayName = g_user.getFullName();
console.log('Current User Display Name: ' + currentUserDisplayName);
// Get the current logged-in user's sys_id
var currentUserSysID = g_user.userID; // As per reference, though g_user.userID is more common now
console.log('Current User Sys ID: ' + currentUserSysID);
// For checking group membership (as shown in reference)
// Note: gs.getUser().isMemberOf() is for server-side.
// For client-side, you'd typically use something like this if you have a field
// or need to call a script include. A direct client-side check for group membership
// without a specific GlideAjax call or pre-loaded data is less common directly via g_user.
// For demonstration, if you were to use a Script Include:
/*
function checkGroupMembership(groupName) {
var ga = new GlideAjax('MyUtilsScript'); // Assuming MyUtilsScript is a Script Include
ga.addParam('sysparm_name', 'isUserInGroup');
ga.addParam('sysparm_group_name', groupName);
ga.getXML(function(response) {
var answer = response.responseXML.documentElement.getAttribute("answer");
if (answer == 'true') {
alert('User is a member of ' + groupName);
} else {
alert('User is NOT a member of ' + groupName);
}
});
}
// To call it: checkGroupMembership('ITIL Users');
*/
Reference Point:
Reference Question 13: How to get the current logged in user system id in the client side?
Answer: g_user.userID;
7. Reference Qualifiers: Filtering Lookup Fields
Reference fields (like ‘Assigned to’ or ‘Configuration Item’) often present a long list of choices. Reference Qualifiers allow you to dynamically filter these lists, showing only relevant records. This significantly improves user efficiency and reduces errors.
How it Works:
There are three types of Reference Qualifiers:
- Simple: Uses basic query conditions (e.g.,
active=true). - Dynamic: Uses pre-defined “Dynamic Filter Options” which can be more complex and context-aware.
- Advanced: Uses JavaScript code to create highly dynamic and complex filtering logic.
Example: Displaying only Active Users in an ‘Assigned To’ field (Simple Reference Qualifier)
In the dictionary entry for the ‘Assigned to’ field (which references the ‘sys_user’ table), add a Reference Qualifier:
- Type: Simple
- Reference qualifier:
active=true
Example: Displaying only users from the same ‘Assignment Group’ (Dynamic Reference Qualifier)
You would first create a Dynamic Filter Option (e.g., “Users in Current Assignment Group”) and then use it in the Reference Qualifier.
Example: Advanced Reference Qualifier for filtered Incidents
Let’s say on a Change Request form, you want to link to an Incident that is assigned to the same Assignment Group as the Change Request and has a Priority of 1 or 2.
In the dictionary entry for the reference field (e.g., ‘Related Incident’):
- Type: Advanced
- Reference qualifier:
javascript: 'assignment_group=' + current.assignment_group + '^priorityIN1,2^stateNOT IN6,7'
(This example assumes ‘current.assignment_group’ correctly resolves to the Assignment Group of the Change Request, and ‘6’ and ‘7’ are resolved states.)
Note: The exact JavaScript syntax can vary based on what `current` object is available and the specific fields you’re referencing.
Reference Point:
Reference Question 48: What are reference qualifiers, and their types? Explain each one in detail and the difference.
Answer: Restricts data in reference/List fields. Types: Simple, Dynamic, Advanced.
8. Dependent Fields (Cascading Dropdowns)
This is a classic UI pattern for filtering choices. If you select ‘Hardware’ as the Category, the ‘Subcategory’ dropdown should only show hardware-related subcategories like ‘Laptop’, ‘Printer’, etc. Conversely, if ‘Software’ is selected, it should show ‘Operating System’, ‘Application’, etc.
How it Works:
This is configured in the dictionary entry of the *dependent* field. You specify which field it depends on. Then, within the choices for the dependent field, you define which choices are available for each value of the parent field.
Example: Category and Subcategory
- Parent Field (Category): Has choices like ‘Hardware’, ‘Software’, ‘Network’.
- Dependent Field (Subcategory):
- Go to the dictionary entry for ‘Subcategory’.
- In the ‘Dependent field’ attribute, select ‘Category’.
- Now, when defining choices for ‘Subcategory’, you’ll see a ‘Dependent value’ column. For example:
- Value: Laptop, Dependent value: Hardware
- Value: Printer, Dependent value: Hardware
- Value: Operating System, Dependent value: Software
- Value: Application, Dependent value: Software
Reference Point:
Reference Question 49: What is dependent value?
Answer: Filters choices in one field based on another, used for cascaded dropdowns.
9. Dynamically Adding or Removing Options from a Choice List
Sometimes, the standard choices for a field need to be augmented or modified based on runtime conditions. For example, if a user is in a specific role, you might want to add an extra “Urgent” option to a Priority field.
How it Works:
This is typically handled with an onChange or onLoad Client Script using g_form.addOption('field_name', 'value', 'label') and g_form.removeOption('field_name', 'value').
Example: Add a Special Option for Admins
function onLoad() {
// Check if the current user is an administrator
if (g_user.hasRole('admin')) {
// Add a new option to the 'State' field
g_form.addOption('state', '99', 'Custom Admin State');
}
}
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if (isLoading || newValue === '') {
return;
}
// Example: If the special option is selected, make a field mandatory
if (newValue === '99') {
g_form.setMandatory('work_notes', true);
} else {
g_form.setMandatory('work_notes', false);
}
}
10. Executing Scripts within UI Policies
While UI Policies are generally declarative, there are times when you need the power of scripting to define the actions or conditions. This is where the “Run scripts” option in UI Policy Actions comes into play.
How it Works:
When creating a UI Policy Action, you can enable the “Run scripts” checkbox. This reveals “Script” and “Script (else)” fields where you can write JavaScript code to execute when the UI Policy condition is met (or not met, if you use “Script (else)”).
Example: Setting Multiple Field Values and Making one Mandatory based on a complex condition
Let’s say on a Change Request, if the ‘Type’ is ‘Normal’ AND the ‘Risk’ is ‘High’, we want to set a specific ‘Assignment Group’, set a ‘Business Impact’ to ‘Medium’, and make a ‘Justification’ field mandatory. This might be too complex for simple UI Policy Actions.
- Table: Change Request
- Short description: Complex UI Policy for Normal/High Risk
- Condition: Type IS Normal^Risk IS High
- Onload: Checked
- Reverse if false: Checked
UI Policy Action:
- Field: (Leave blank, as we’re using script)
- Run scripts: Checked
- Script:
function executeUIAction() { g_form.setValue('assignment_group', 'your_assignment_group_sysid'); // Replace with actual sys_id g_form.setValue('business_impact', 'medium'); // Assuming 'medium' is a valid value g_form.setMandatory('justification', true); } executeUIAction(); - Script (else):
function executeUIActionElse() { g_form.setValue('assignment_group', ''); g_form.setValue('business_impact', ''); g_form.setMandatory('justification', false); } executeUIActionElse();
Reference Point:
Reference Question 63: Can you write script in UI policy?
Answer: Yes, by enabling the “Run scripts” checkbox in a UI Policy Action.
Conclusion
By mastering these ten ServiceNow client script scenarios, you’ve gained valuable tools to enhance user experience, enforce business rules, and build more intelligent and efficient forms. Remember to always consider UI Policies first for declarative tasks and leverage Client Scripts for more complex, programmatic logic. Practice these examples, adapt them to your specific business needs, and you’ll be well on your way to becoming a ServiceNow form customization expert.
The ability to dynamically control form behavior is a cornerstone of effective ServiceNow development. Continue exploring, experimenting, and refining your skills – the possibilities for innovation are endless!