How to Use GlideAjax in ServiceNow: A Comprehensive Guide

Unlocking Client-Server Magic: Your Definitive Guide to GlideAjax in ServiceNow

Ever found yourself building a ServiceNow form, only to hit a wall? You need some data that lives on the server, or a complex calculation that can’t possibly be done in a simple client script. Perhaps you want to validate a field against a massive database table without grinding the user experience to a halt. If these scenarios sound familiar, congratulations! You’ve just discovered the exact problem that GlideAjax was born to solve.

Think of GlideAjax as your personal, high-speed messenger service within ServiceNow. It allows your client-side scripts (the ones running in the user’s browser) to chat directly with server-side scripts (the powerful code running on the ServiceNow instance itself). This opens up a world of possibilities, enabling dynamic, data-driven forms and a far more responsive user experience. If you’re ready to level up your ServiceNow development skills, stick around. We’re about to demystify GlideAjax, making you a master of this essential API.

What is GlideAjax? Your ServiceNow Bridge to the Server

At its heart, GlideAjax is a client-side API (Application Programming Interface) in ServiceNow. What does that mean in plain English? It’s a set of tools and functions available to your client scripts that allow them to initiate communication with the server without refreshing the entire page. It’s like sending a quick text message to a friend instead of writing a full letter and mailing it.

The primary purpose of GlideAjax is twofold:

  • Get Data from the Server to the Client: Imagine you need to auto-populate a user’s department and location as soon as their name is selected. That data lives in the database on the server. GlideAjax fetches it for your client script.
  • Execute Server-Side Script from Client Script: Sometimes, you need to perform complex logic, calculations, or validations that are too heavy or sensitive for the client side. GlideAjax lets you trigger a server-side function to do the heavy lifting and then return the result.

Why Not Just GlideRecord in Client Script? (The Performance Pitfall)

New developers often wonder, “Can’t I just use GlideRecord directly in my client script?” While technically possible in some scenarios (and you might see old code floating around that does this), it’s considered a significant anti-pattern and a major performance killer. Using GlideRecord directly on the client side forces the browser to wait for database queries, potentially freezing the user interface and leading to a terrible user experience. It’s like asking your friend to send you a copy of every single book in their library just to find one sentence.

Similarly, g_form.getReference(), another method to fetch related record data, can also cause synchronous calls and UI delays if not used carefully. GlideAjax, especially its asynchronous variant, bypasses these issues by providing a much more efficient and user-friendly way to interact with the server. In fact, one of the best practices for client-side scripting is to avoid using g_form.getReference for exactly this reason, favoring asynchronous GlideAjax instead.

The Dynamic Duo: Client Script and Script Include

To really make GlideAjax sing, you need two key components working in harmony:

The Client Script: The Initiator

This is where your GlideAjax call originates. It’s typically an onChange, onLoad, or onSubmit client script that detects a user action (like changing a field value) or loads a form, and then decides it needs to ask the server for something.

The Script Include: The Server-Side Brains

This is where the actual server-side logic resides. A Script Include is essentially a reusable block of server-side JavaScript code. When your GlideAjax call hits the server, it’s directed to a specific function within a specific Script Include. This function performs the requested action (e.g., querying the database, performing calculations) and sends the result back to your client script.

What is it?

Script Includes are crucial for keeping your code modular, reusable, and maintainable. Instead of embedding complex server-side logic directly into business rules or other scripts, you centralize it in a Script Include. This makes it easier to manage, update, and debug. There are a few types of Script Includes, but for GlideAjax, we’re primarily concerned with Client Callable Script Includes.

The “Client Callable” Checkbox

This is vital! For a Script Include to be accessible via GlideAjax from the client side, you MUST tick the “Client callable” checkbox when you define it. If you forget this, your GlideAjax calls will fail silently, leading to endless head-scratching.

Public vs. Private Functions

Within a Client Callable Script Include, you’ll define functions. By convention, functions whose names start with an underscore (e.g., _myPrivateFunction()) are considered “private.” This means they cannot be directly called from the client side via GlideAjax. They are internal helper functions for other public functions within the same Script Include. Functions without the underscore are public and callable.

The Role of sysparm_name

When you make a GlideAjax call, you’re not just calling a Script Include; you’re calling a specific function within that Script Include. How does GlideAjax know which function? Through a special parameter called sysparm_name. This parameter tells the server exactly which public function in your Client Callable Script Include to execute.

GlideAjax in Action: Syntax and Types

Alright, let’s get down to brass tacks. The basic structure of a GlideAjax call is quite consistent. You instantiate a new GlideAjax object, specify your Script Include, add any necessary parameters, and then execute it.

The Core Syntax

var ga = new GlideAjax('YourScriptIncludeName'); // 1. Name of your Client Callable Script Include
ga.addParam('sysparm_name', 'yourFunctionName'); // 2. The specific function to call within the Script Include
ga.addParam('sysparm_custom_param1', g_form.getValue('field_name')); // 3. Optional: Pass data to the server
ga.addParam('sysparm_custom_param2', 'some_static_value'); // 4. Optional: Pass more data
// ... then you make the call: asynchronous or synchronous

Let’s break down those critical steps:

  1. new GlideAjax('YourScriptIncludeName'): This line creates a new GlideAjax object and tells it which Client Callable Script Include on the server it should communicate with. The name must be exact, case-sensitive.
  2. ga.addParam('sysparm_name', 'yourFunctionName'): This is crucial. It defines which public function within your specified Script Include will be executed. Remember, this parameter name must be sysparm_name.
  3. ga.addParam('sysparm_custom_param', 'value'): These are your custom input parameters. You can name these anything you want (as long as they start with sysparm_ to avoid conflicts with reserved GlideAjax parameters). These values will be accessible inside your Script Include function. Here, we’re grabbing the value of a form field using g_form.getValue().

Now, once you’ve set up your request, you have a choice to make: how do you want to handle the server’s response? This brings us to the two types of GlideAjax calls:

Asynchronous GlideAjax: The User-Friendly Path (getXMLAnswer)

This is the preferred and most common way to use GlideAjax. Asynchronous means “not happening at the same time.” When you make an asynchronous GlideAjax call, your client script sends the request to the server and then continues executing the rest of its code without waiting for a response. The user can still interact with the form, scroll, type, and click. Once the server processes the request and sends back a response, a special function you’ve defined (a “callback function”) is triggered to handle that response.

This approach leads to a much better user experience because it prevents the UI from freezing. It’s like ordering food at a restaurant – you place your order and then continue chatting or looking at your phone until the food arrives, rather than standing at the counter holding your breath.

Syntax for Asynchronous GlideAjax:

var ga = new GlideAjax('YourScriptInclude');
ga.addParam('sysparm_name', 'yourFunction');
ga.addParam('sysparm_caller', g_form.getValue('u_caller')); // Example custom param
ga.getXMLAnswer(callbackFunction); // This is the async call!

function callbackFunction(response) {
    var answer = response; // 'response' contains the data returned from the server
    // Process the response here
    alert('Server said: ' + answer);
}

Notice the getXMLAnswer(callbackFunction). This method sends the request and specifies which function (callbackFunction in this example) should be called when the server’s answer arrives. The server’s response is passed as an argument to your callback function.

Synchronous GlideAjax: Handle with Care (getXMLWait)

Synchronous means “happening at the same time.” When you make a synchronous GlideAjax call, your client script sends the request to the server and then pauses its execution, waiting for the server’s response before doing anything else. During this wait, the user interface will be unresponsive – it “locks” the form. This can be a jarring and frustrating experience for the user if the server takes even a short amount of time to respond.

Synchronous calls should be used very, very sparingly, typically only in situations where the subsequent client-side code absolutely cannot proceed until the server’s response is received, and where the potential for UI freezing is acceptable (e.g., stopping a form submission based on a server-side validation). An example could be stopping a form submission if a selected caller is a ‘Contractor’ based on server-side logic.

Syntax for Synchronous GlideAjax:

var ga = new GlideAjax('YourScriptInclude');
ga.addParam('sysparm_name', 'yourFunction');
ga.addParam('sysparm_user_name', "Bob"); // Example custom param
ga.getXMLWait(); // This is the sync call! The script waits here.
var answer = ga.getAnswer(); // Once the server responds, get the answer.
alert(answer);
// The script only continues *after* the server has responded and ga.getAnswer() has retrieved it.

Here, you use getXMLWait(). After this line, the script literally waits. Once the response comes back, you can then retrieve the answer using ga.getAnswer(). While it provides a simpler flow for sequential logic, the negative impact on user experience is almost always a reason to avoid it.

Building Your First GlideAjax Call: A Step-by-Step Example

Let’s walk through a practical scenario: Imagine you have a form where users select a “Caller.” You want to automatically fetch and display a message indicating if this caller is a “Contractor” or “Employee” and update a read-only field based on this.

Scenario: Fetching User Role Details

We’ll create an onChange client script on the ‘Caller’ field. When a caller is selected, we’ll send their User ID to a Script Include. The Script Include will check if the user is a contractor and return a suitable message. Our client script will then display this message in an ‘Information’ field.

Step 1: Create Your Script Include (Server-Side Logic)

Navigate to System Definition > Script Includes and click “New.”

  • Name: UserInfoFetcher (or something descriptive)
  • Client callable: (Crucial! Check this box)
  • Script:
var UserInfoFetcher = Class.create();
UserInfoFetcher.prototype = Object.extendsObject(AbstractAjaxProcessor, {

    // This is our public function that GlideAjax will call via sysparm_name
    getUserType: function() {
        var userID = this.getParameter('sysparm_userID'); // Get the parameter passed from client script
        var userName = this.getParameter('sysparm_userName'); // Example: getting another param

        var grUser = new GlideRecord('sys_user');
        if (grUser.get(userID)) { // Query the sys_user table
            if (grUser.u_is_contractor == true) { // Assuming a custom field 'u_is_contractor'
                return userName + ' is a Contractor!';
            } else {
                return userName + ' is an Employee.';
            }
        }
        return 'User not found or type unknown.';
    },

    // Example of a private function - cannot be called directly from client
    _privateHelper: function() {
        // This function could be used internally by getUserType, but not directly by GlideAjax
        gs.log('This is a private helper function.');
    },

    type: 'UserInfoFetcher'
});

Explanation of the Script Include:

  • var UserInfoFetcher = Class.create(); and UserInfoFetcher.prototype = Object.extendsObject(AbstractAjaxProcessor, { ... });: This is the standard boilerplate for a Client Callable Script Include. AbstractAjaxProcessor is the base class that provides methods like getParameter().
  • getUserType: function() { ... }: This is our public function. Its name (getUserType) will be passed via sysparm_name from the client script.
  • this.getParameter('sysparm_userID'): This method (provided by AbstractAjaxProcessor) allows us to retrieve values passed from the client script using ga.addParam(). Remember, your client-side parameter names must start with sysparm_ to be accessible here.
  • The logic inside getUserType: It performs a GlideRecord query on the sys_user table to get the user’s details. (Note: For this example, I’m assuming a custom boolean field `u_is_contractor` exists on `sys_user` for demonstration. You might check roles, groups, or other fields in a real scenario.)
  • return '...';: The string returned by this function is what the client script’s callback function will receive as its response.

Step 2: Craft Your Client Script (Client-Side Request)

Navigate to System Definition > Client Scripts and click “New.”

  • Name: CheckCallerType
  • Table: The table your form is on (e.g., Incident, sc_req_item, etc.)
  • UI Type: All
  • Type: onChange
  • Field name: Caller (or whatever your reference field to sys_user is named)
  • Script:
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
    if (isLoading || newValue === '') {
        g_form.setValue('u_information_field', ''); // Clear our info field if no caller or loading
        return;
    }

    // 1. Instantiate GlideAjax, pointing to our Script Include
    var ga = new GlideAjax('UserInfoFetcher');

    // 2. Specify the function in the Script Include to call
    ga.addParam('sysparm_name', 'getUserType');

    // 3. Pass the user's sys_id and display name as parameters to the server
    ga.addParam('sysparm_userID', newValue); // newValue is the sys_id of the selected caller
    ga.addParam('sysparm_userName', g_form.getDisplayBox('caller').value); // Get display value

    // 4. Make the asynchronous call and define the callback function
    ga.getXMLAnswer(function(response) {
        var answer = response;
        // 5. Process the response received from the server
        g_form.setValue('u_information_field', answer); // Update our info field
    });
}

Explanation of the Client Script:

  • onChange function: This is standard Client Script boilerplate. We check isLoading and newValue to ensure we only run when a caller is actually selected.
  • var ga = new GlideAjax('UserInfoFetcher');: Creates the GlideAjax object, referencing our Script Include by its exact name.
  • ga.addParam('sysparm_name', 'getUserType');: Tells the Script Include to run the getUserType function.
  • ga.addParam('sysparm_userID', newValue);: Passes the sys_id of the newly selected caller to the server.
  • ga.addParam('sysparm_userName', g_form.getDisplayBox('caller').value);: Passes the display name of the caller. This is more user-friendly for the message.
  • ga.getXMLAnswer(function(response) { ... });: This is the asynchronous call. It takes an anonymous function as its argument, which serves as our callback.
  • var answer = response;: Inside the callback, the response variable holds whatever our Script Include function returned.
  • g_form.setValue('u_information_field', answer);: Updates a field (e.g., a multi-line text field or string field) on the form with the message received from the server.

And there you have it! When a user selects a Caller, the client script will asynchronously reach out to the server, get the user type, and update the form without any UI freezes. That’s the power of GlideAjax!

A Quick Look at Synchronous for Specific Cases

Let’s revisit our “Contractor stops form submission” scenario. If you absolutely needed to block submission for a contractor, a synchronous call might look like this (but remember the strong warnings!):

function onSubmit() {
    var callerID = g_form.getValue('caller');
    if (callerID == '') {
        return true; // No caller, proceed
    }

    var ga = new GlideAjax('UserInfoFetcher');
    ga.addParam('sysparm_name', 'getUserType');
    ga.addParam('sysparm_userID', callerID);
    ga.addParam('sysparm_userName', g_form.getDisplayBox('caller').value);

    ga.getXMLWait(); // WARNING: This blocks the UI!
    var answer = ga.getAnswer();

    if (answer.includes('Contractor')) {
        g_form.addErrorMessage('Contractors cannot submit this form directly.');
        return false; // Stop form submission
    }

    return true; // All clear, proceed with submission
}

In this example, the onSubmit script *must* wait for the server’s response before deciding whether to let the form submit. This is one of the few legitimate (though still cautioned) uses for synchronous GlideAjax. However, if this server call takes more than a split second, the user will experience a frozen form.

Best Practices for a Smooth GlideAjax Experience

Like any powerful tool, GlideAjax comes with best practices to ensure optimal performance, maintainability, and user experience. Following these tips will save you headaches down the road:

  1. Prioritize Asynchronous Calls (getXMLAnswer): This is the golden rule. Always opt for asynchronous unless you have an exceptionally strong, unavoidable reason for synchronous behavior (and even then, question it twice!). A responsive UI is paramount for user satisfaction.
  2. Keep Script Includes Client-Callable: Double-check that “Client callable” checkbox. It’s the most common reason for GlideAjax calls failing.
  3. Validate Inputs Server-Side: Never trust data coming from the client. Always validate and sanitize parameters received in your Script Include functions to prevent security vulnerabilities and unexpected behavior.
  4. Handle Responses Gracefully: In your client-side callback function, always assume the server might not return exactly what you expect. Check for empty responses, error messages, or unexpected data formats before trying to use the data.
  5. Avoid Excessive Calls: Don’t make multiple GlideAjax calls in rapid succession for related data if one call could fetch it all. Each call has overhead. Bundle requests where logical, perhaps by returning JSON objects with multiple pieces of data.
  6. Use JSON for Complex Data: If your Script Include needs to return more than a simple string (e.g., multiple field values, an array of options), return a JSON string from your Script Include (return JSON.stringify(myObject);) and then parse it on the client side (var data = JSON.parse(response);). This is far more efficient than multiple parameters or complex string parsing.
  7. Enclose Client Script Code in Functions: Always define your client script logic within the provided onLoad, onChange, onSubmit, or onCellEdit functions. Avoid global client scripting where possible.
  8. Don’t Manipulate the DOM Directly: Stick to the g_form object for interacting with form fields (g_form.setValue(), g_form.getValue(), g_form.addInfoMessage(), etc.). Directly manipulating the Document Object Model (DOM) can lead to unexpected behavior and break in future ServiceNow upgrades.

Troubleshooting Common GlideAjax Headaches

Even seasoned developers hit snags with GlideAjax. Here are some common issues and how to resolve them:

“My Callback Isn’t Firing!” or “Empty Response!”

  • Is the Script Include “Client callable”? (Go back and check!)
  • Is the Script Include name spelled correctly in new GlideAjax()? (Case-sensitive!)
  • Is sysparm_name correctly pointing to a PUBLIC function? (Again, case-sensitive, no underscores for client-callable functions!)
  • Are there errors in your Script Include? Check the ServiceNow system logs (System Logs > All) for server-side errors. A server error will prevent a proper response.
  • Is your client script sending the parameters correctly? Use alert() or console.log() in your client script to verify parameter values before sending.
  • Is your Script Include actually returning a value? A function that doesn’t explicitly return something will send back ‘null’ or an empty string.
  • Is the callback function correctly defined and accessible? Make sure there are no typos in the callback function name passed to getXMLAnswer().

“My Form Froze!”

  • Are you using getXMLWait()? This is the most likely culprit. Re-evaluate if an asynchronous approach is truly impossible for your use case. If it is, ensure your server-side logic is as fast as humanly possible.
  • Is your server-side Script Include taking too long? Long-running database queries or complex calculations in your Script Include can cause delays even with asynchronous calls, though they won’t freeze the UI. Optimize your server-side code.

“Security Concerns”

  • Never expose sensitive data through GlideAjax that shouldn’t be seen by the client. Even if a field is hidden, the data might be inspectable.
  • Implement proper ACLs (Access Control Lists) on tables. Your Script Include might run on the server, but it should still respect user permissions when querying data.
  • Sanitize and validate all client-supplied input. Prevent injection attacks or unexpected behavior by never directly using client input in database queries without proper escaping or validation.

GlideAjax in the Interview Hot Seat

GlideAjax is a common topic in ServiceNow developer interviews. Expect questions like:

  • “What is GlideAjax and why is it used?” (Client-side API for client-server communication, fetching data, executing server logic).
  • “What’s the difference between synchronous and asynchronous GlideAjax?” (Blocking vs. non-blocking UI, getXMLWait vs. getXMLAnswer).
  • “When would you use synchronous GlideAjax?” (Carefully explain the rare scenarios like onSubmit validation, emphasizing the UX impact and preference for async).
  • “How do you call a Script Include from a Client Script?” (Via GlideAjax, mentioning sysparm_name and “Client callable” checkbox).
  • “What are some best practices for using GlideAjax or client scripts in general?” (Asynchronous preference, g_form, no DOM manipulation, JSON, input validation).
  • “Can you use GlideRecord in a Client Script?” (Yes, but it’s a poor practice due to performance issues; GlideAjax is the recommended alternative).

Being able to articulate these points clearly and with practical examples will demonstrate a strong understanding of ServiceNow development principles.

Conclusion: Master the Client-Server Dance

GlideAjax is more than just another API; it’s a fundamental pattern for building dynamic, efficient, and user-friendly applications in ServiceNow. By mastering the art of client-server communication, you empower your forms to be smarter, your validations to be more robust, and your overall user experience to be significantly smoother. While it might seem a bit daunting at first, the core concepts are straightforward: a client script initiates a request, a client-callable Script Include processes it, and an asynchronous callback handles the response.

Keep the best practices in mind, especially the power of asynchronous calls, and you’ll soon be weaving complex server-side logic into your client scripts with confidence. Go forth, experiment, and make your ServiceNow forms truly interactive!

Scroll to Top