Mastering ServiceNow Navigation: A Comprehensive GlideNavigation API Tutorial
Welcome, fellow ServiceNow enthusiasts! If you’ve been navigating the world of ServiceNow development, you’ve undoubtedly encountered the need to programmatically control user navigation. Whether you’re building custom applications, streamlining workflows, or enhancing user experience, understanding how to direct users to the right place at the right time is crucial. In this in-depth guide, we’ll dive deep into the GlideNavigation API, a powerful tool that allows you to achieve just that. We’ll cover its core functionalities, practical applications, and provide insights relevant to your daily development and even those tricky interview questions.
This tutorial is built with the latest ServiceNow versions in mind, specifically targeting the Washington DC release, and drawing from experience gained across several previous versions including Rome, San Diego, Tokyo, Utah, and Vancouver. This ensures the information is current and practical.
Understanding GlideNavigation API: The Navigator’s Toolkit
At its heart, the GlideNavigation API is a server-side API designed to manipulate the user’s navigation experience within the ServiceNow platform. Think of it as your digital GPS for guiding users to specific records, lists, pages, or even external URLs. It’s a fundamental part of creating dynamic and responsive user interfaces.
Core Functions and Their Applications
The GlideNavigation API offers a suite of methods, each serving a distinct purpose. Let’s explore some of the most commonly used ones:
1. `navto()` – The Workhorse of Navigation
This is perhaps the most versatile method. `navto()` allows you to redirect the user to a specified destination. The destination can be defined in various ways:
- A specific record: Navigate directly to a form view of a particular record.
- A list of records: Take the user to a list view, optionally with filters applied.
- A UI page: Redirect to a custom UI page you’ve built.
- An external URL: Send the user to an external website.
Syntax: `GlideNavigation.navto(target);`
Example 1: Navigating to a specific incident record
var incidentSysId = 'your_incident_sys_id_here'; // Replace with the actual sys_id
GlideNavigation.navto('incident.do?sys_id=' + incidentSysId);
In this example, we’re constructing a URL to directly open the incident form with the specified `sys_id`. This is incredibly useful after creating or updating a record to immediately show the user the result.
Example 2: Navigating to a filtered list of active incidents
GlideNavigation.navto('incident_list.do?sysparm_query=active=true^priority=1');
Here, we’re directing the user to the incident list (`incident_list.do`) and applying a query to show only active incidents with a priority of 1 (critical). This is a great way to guide users to relevant data quickly.
Example 3: Navigating to a custom UI page
GlideNavigation.navto('my_custom_ui_page.do');
If you have a custom UI page named `my_custom_ui_page.do`, this will smoothly transition the user to it.
2. `redirect()` – Similar to `navto()`, but with Nuances
While `navto()` is generally preferred for its flexibility, `redirect()` also exists. It’s often used in contexts where a simple redirection is needed. However, `navto()` is more powerful for constructing complex navigation targets.
Example:
var userSysId = gs.getUserID();
GlideNavigation.redirect('sys_user.do?sys_id=' + userSysId);
This would redirect the user to their own user record. In most modern development, you’ll find yourself using `navto()` more frequently.
3. `openPopup()` – For Focused User Interactions
Sometimes, you don’t want to take the user away from their current context. This is where `openPopup()` shines. It displays a specified URL in a modal pop-up window.
Syntax: `GlideNavigation.openPopup(target, width, height);`
Example: Opening a task form in a popup
var taskSysId = 'your_task_sys_id_here';
GlideNavigation.openPopup('sc_task.do?sys_id=' + taskSysId, 800, 600); // Width 800px, Height 600px
This is incredibly useful for allowing users to quickly view or edit related records without losing their current work. For instance, when working on an incident, you might want to open associated incident tasks in a popup.
4. `setLocation()` – A Client-Side Companion
While GlideNavigation is primarily server-side, it’s important to mention its client-side counterpart: `g_navigation.setLocation()`. This method is used within client scripts (like onSubmit, onLoad, onChange) to change the browser’s location.
Syntax: `g_navigation.setLocation(url);`
Example: Redirecting after form submission in a client script
// In an onSubmit client script on the 'incident' table
function onSubmit() {
if (g_form.isNewRecord()) {
// After saving a new incident, redirect to a custom page
g_navigation.setLocation('my_custom_confirmation_page.do');
return false; // Prevent default form submission if redirecting
}
return true;
}
This client-side method is essential for immediate feedback or guiding users after an action they’ve just performed on the form.
Permissions, Users, and Groups: The Foundation of Access Control
Before we delve deeper into navigation, it’s crucial to touch upon how permissions are managed in ServiceNow, as navigation often depends on a user’s access rights. Based on our reference:
User and Group Management
- User Table: `sys_user`
- Group Table: `sys_user_group`
- Group Membership Table: `sys_user_grmember`
Adding Permissions (Roles)
Permissions are managed through roles. You can add roles to users or groups.
- To a User: Records are created in the `sys_user_has_role` table.
- To a Group: Records are created in the `sys_group_has_role` table.
Best Practice for Permissions: As the reference rightly points out, assigning roles to groups is the best practice. This simplifies user management. When an employee leaves or changes roles, you simply remove them from the relevant group(s), and their permissions are automatically revoked. This is far more efficient and less error-prone than managing roles individually for each user.
Scripting User/Group Creation and Role Assignment:
// Creating a user
var userGr = new GlideRecord('sys_user');
userGr.initialize();
userGr.username = 'jdoe';
userGr.firstname = 'John';
userGr.lastName = 'Doe';
userGr.email = 'jdoe@example.com';
userGr.insert();
// Creating a group
var newGr = new GlideRecord('sys_user_group');
newGr.initialize();
newGr.name = 'IT Support Team';
// Assuming 'manager_sys_id' is the sys_id of the manager user
newGr.manager = 'manager_sys_id';
newGr.email = 'itsupport@example.com';
newGr.description = 'Handles all IT-related incidents and requests.';
newGr.insert();
// Adding a role to a user
var userRole = new GlideRecord('sys_user_has_role');
userRole.setValue('user', userGr.sys_id); // Using the sys_id of the created user
// Assuming 'admin_role_sys_id' is the sys_id of the 'admin' role
userRole.setValue('role', 'admin_role_sys_id');
userRole.insert();
// Adding a role to a group
var grpRole = new GlideRecord('sys_group_has_role');
grpRole.setValue('group', newGr.sys_id); // Using the sys_id of the created group
// Assuming 'itil_role_sys_id' is the sys_id of the 'itil' role
grpRole.setValue('role', 'itil_role_sys_id');
grpRole.insert();
// Adding a user to a group
var grMem = new GlideRecord('sys_user_grmember');
grMem.user = userGr.sys_id; // Use the sys_id of the user
grMem.group = newGr.sys_id; // Use the sys_id of the group
grMem.insert();
// Removing a user from a group
var grMemToRemove = new GlideRecord('sys_user_grmember');
grMemToRemove.addQuery('user', userGr.sys_id);
grMemToRemove.addQuery('group', newGr.sys_id);
grMemToRemove.query();
if (grMemToRemove.next()) {
grMemToRemove.deleteRecord();
}
User Delegation: Enabling Collaboration
User delegation is a powerful feature allowing one user to perform actions on behalf of another. This is particularly useful when a user is on leave or unavailable. The delegated user gains access to perform tasks, receive notifications, and even handle approvals for the original user.
How it works: The original user configures delegation settings on their profile, specifying who can act on their behalf, the duration, and the types of permissions granted (assignments, notifications, approvals).
Beyond Basic Navigation: Contextual Actions and UI Policies
GlideNavigation isn’t used in a vacuum. It often works in conjunction with other ServiceNow features to provide a seamless user experience.
UI Policies and Client Scripts: Triggering Navigation
You’ll frequently use GlideNavigation within UI Policies or Client Scripts to automate navigation based on specific conditions.
- UI Policies: While UI Policies are primarily for manipulating form elements (mandatory, read-only, visibility), they can trigger Client Scripts, which in turn can use GlideNavigation. The “Run scripts” option in UI Policy Actions is your gateway here.
- Client Scripts:
- `onLoad`: Useful for setting initial navigation based on form load conditions.
- `onChange`: Great for redirecting when a field’s value changes.
- `onSubmit`: Ideal for guiding users after a record is saved.
Example: Redirecting to a different form after closing an incident
// In an onSubmit client script on the 'incident' table
function onSubmit() {
if (g_form.getValue('state') == '7' && g_form.isChanged('state')) { // If state is changed to Closed
// Let's say we want to navigate to a custom 'Incident Resolved' page
g_navigation.setLocation('incident_resolved_view.do?sys_id=' + g_form.getUniqueValue());
return false; // Prevent default behavior if redirecting
}
return true;
}
Data Policies: Server-Side Navigation Control
Data Policies, unlike UI Policies, operate on the server-side (and can also affect the client). While they don’t directly execute `GlideNavigation`, they can enforce conditions that might lead to a developer implementing server-side navigation using `GlideNavigation.navto()` in a Business Rule triggered by the data policy’s actions.
Navigating Between Core Records: Incident, Problem, Change
The relationships between Incident, Problem, and Change Management are fundamental to IT Service Management (ITSM). GlideNavigation plays a role in linking these processes.
The ITSM Lifecycle
Incident: A sudden interruption of service. When something breaks, an incident is created.
Problem: If the same issue occurs repeatedly, it’s a problem. A problem record aims to find the root cause.
Change Request: If modifications are needed to fix a problem or implement an enhancement, a change request is created.
Scripting Record Creation and Navigation
You’ll often create one type of record from another and then navigate the user to the newly created record.
// Example: Creating an Incident and navigating to it
var grIncident = new GlideRecord('incident');
grIncident.initialize();
grIncident.caller_id = gs.getUserID(); // Set caller to current user
grIncident.short_description = 'User reporting slow system performance';
grIncident.description = 'The system is experiencing significant slowdowns, impacting productivity.';
grIncident.assignment_group = 'your_assignment_group_sys_id'; // Example assignment group
var newIncidentSysId = grIncident.insert();
if (newIncidentSysId) {
// Navigate to the newly created incident
GlideNavigation.navto('incident.do?sys_id=' + newIncidentSysId);
gs.addInfoMessage('Incident created successfully: ' + grIncident.number);
} else {
gs.addErrorMessage('Failed to create incident.');
}
// Example: Creating a Problem from an Incident (typical in a Business Rule)
// Assuming 'current' is the incident record being processed
var grProblem = new GlideRecord('problem');
grProblem.initialize();
grProblem.caller_id = current.caller_id;
grProblem.short_description = 'Recurring issue: ' + current.short_description;
grProblem.description = 'Root cause analysis needed for repeated incidents related to: ' + current.short_description;
grProblem.work_notes = 'Created from incident ' + current.number;
grProblem.insert();
// Update the incident to link it to the problem
current.problem_id = grProblem.sys_id;
current.update();
// Optionally, navigate to the new problem record
// GlideNavigation.navto('problem.do?sys_id=' + grProblem.sys_id);
Business Rule Logic for Related Records
You’ll often find GlideNavigation usage in Business Rules, especially ‘after’ insert/update rules:
- Closing Parent Incident: As per the provided Q&A (Q26), an ‘after update’ Business Rule can be written to close child incidents when a parent incident is closed. While it doesn’t directly use `navto`, it demonstrates controlling related record states.
- Closing Related Incidents from Problem: Similarly (Q28), when a problem is closed, associated incidents can be updated.
- Preventing Closure with Open Tasks: (Q27) An ‘before update’ Business Rule is perfect for checking open incident tasks before allowing an incident closure. If tasks are open, an error message is shown, and `current.setAbortAction(true)` prevents the closure. This logic is crucial for maintaining data integrity.
Essential Field Types and Dictionary Concepts
Understanding field types and their configurations is key to effective navigation and form design.
Common Field Types
- Reference: Links to another record (e.g., User, Assignment Group).
- String: Text field.
- List: Allows selection of multiple records from a referenced table.
- Choice: Dropdown with predefined options.
- Email: For email addresses.
- Date/Time: For date and time values.
- Date: For date values only.
- Boolean: True/False.
- Integer: Whole numbers.
- Journal: For comments and work notes.
- Attachment: For file uploads.
Attributes: Modifying Field Behavior
Attributes are powerful modifiers applied at the field’s dictionary entry level. They alter how a field behaves on the form.
- `no_email`: Prevents email notifications for changes to this field.
- `no_attachment`: Disables attachments for this field (useful on tables where attachments aren’t needed).
- `tree_picker`: Displays a hierarchical tree view for selection in reference fields.
Enabling/Disabling Attachments: To disable attachments on a form, you can add the `no_attachment` attribute to the ‘attachment’ field in the dictionary entry of the table. For example, on the `incident` table, you’d find the dictionary entry for the `sys_attachment` field and add `no_attachment` to its attributes.
Dictionary Overrides
When a table extends another (e.g., `incident` extends `task`), fields from the parent table can have their properties modified in the child table using Dictionary Overrides. This is essential for tailoring fields like `priority` or `state` to the specific needs of a table.
Dependent Values
This feature creates cascading dropdowns. For instance, selecting a ‘Category’ (parent) dynamically filters the available ‘Subcategory’ (dependent) options. This significantly improves user experience by presenting only relevant choices.
Calculated Fields
When a field’s value needs to be computed based on other fields, you can use a calculated field. The calculation is defined in the dictionary entry, often using the `current` object.
// Example: A 'Full Name' field calculated from 'First Name' and 'Last Name'
// In the dictionary entry for 'Full Name':
// Type: Calculated
// Script: current.first_name + ' ' + current.last_name;
Controlling Field Behavior: UI Policies vs. Data Policies
Both UI Policies and Data Policies are used to enforce business rules and control field behavior, but they operate at different levels:
UI Policies
- Client-side: Primarily impact the user interface in real-time.
- Actions: Make fields mandatory, read-only, visible/hidden, set default values, execute client scripts.
- Global checkbox: If checked, applies to all views; otherwise, specific views can be targeted.
- Reverse if false: Reverts changes when the condition becomes false.
- On Load: Scripts execute when the form loads.
- Inherit: UI Policies can be inherited by child tables.
- Scripting: Can be enabled via the “Run scripts” checkbox in UI Policy Actions.
Data Policies
- Client & Server-side: Enforce data integrity regardless of how the data is entered (form, import, API).
- Actions: Similar to UI Policies (mandatory, read-only, visible/hidden, set default values).
- Works universally: More robust for ensuring data consistency.
Conversion and Limitations
You can convert UI Policies to Data Policies (and vice versa, with limitations). However, Data Policies cannot replicate UI Policies that control:
- Data visibility (client-side hiding/showing based on UI context).
- View control.
- Related list visibility.
- Client-side scripting execution specific to UI interactions.
Troubleshooting Common Navigation Issues
Even with powerful APIs, things can go wrong. Here are some common pitfalls and how to address them:
Troubleshooting Navigation Problems
- Incorrect Sys_ID: Always double-check that you’re using the correct `sys_id` for records when constructing navigation URLs. Use `gs.log()` or `gs.addInfoMessage()` to print the `sys_id` you’re trying to use.
- Permissions Denied: If a user can’t navigate to a record or page, it’s likely a permission issue. Ensure the user has the necessary roles. Remember the best practice of assigning roles to groups! Check the `sys_user_has_role` and `sys_group_has_role` tables.
- Script Errors: Syntax errors in your GlideNavigation scripts (especially in Business Rules or Client Scripts) will prevent navigation. Review your code for typos, incorrect method calls, or missing semicolons.
- UI Policy/Data Policy Conflicts: Sometimes UI Policies and Data Policies can conflict, leading to unexpected behavior. Temporarily disable them to isolate the issue.
- Caching Issues: In rare cases, browser or server-side caching might cause issues. Try clearing your browser cache or performing an `impersonation` as the affected user.
- External URL Failures: If navigating to an external URL, ensure the URL is correct and that ServiceNow’s outbound security rules allow access.
Interview Relevance
Understanding the GlideNavigation API and related concepts is crucial for ServiceNow developer interviews. Here’s why:
Key Interview Takeaways
- GlideNavigation API: Be prepared to explain `navto()`, `openPopup()`, and their use cases.
- Client vs. Server-Side: Differentiate between `GlideNavigation` (server) and `g_navigation` (client).
- Business Rules & Client Scripts: Know how to trigger navigation from these scripts.
- Permissions & Best Practices: Discuss user/group management and the importance of group-based role assignment.
- ITSM Relationships: Explain the flow between Incident, Problem, and Change, and how navigation facilitates this.
- UI Policies vs. Data Policies: Understand their differences, use cases, and conversion.
- Field Types & Attributes: Be familiar with common field types and how attributes modify behavior.
- `current` Object: Understand its role in server-side scripting for setting field values and calculations.
Conclusion
The GlideNavigation API is an indispensable tool in the ServiceNow developer’s arsenal. By mastering its capabilities, you can create intuitive user journeys, streamline complex workflows, and build truly dynamic applications. Remember to always consider the user’s context, permissions, and the overall flow of your application. Practice implementing these techniques in your development instances, and you’ll soon find yourself navigating the platform with newfound confidence and efficiency. Happy coding!