
- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
on 10-27-2017 11:23 AM
Click here for an updated version of the GlideAJAX Example Cheat Sheet
It can be hard to remember all of the Client and Server elements of a GlideAjax call. I created a simple example with color coding to help make sure I don't miss any of the details when I'm making a new call from scratch. I hope this helps. I attached a Word doc as well as the image and text below for convenience.
Note: Client callable must be checked in the Script Include for this to work
# Yellow:
This is the name of the class you create. This is usually the same as the name of the Script Include.
# Magenta:
This is the name of the function to use in the script include. You can have a single script include with multiple functions that accept and return different parameters. For example, you could create a single Script Include for getting data related to users and keep adding functions to it as needed.
# Green:
This is a parameter that is passed through the URL of the AJAX call. You can add more than one parameter. usually this is information you will use to make a GlideRecord call in the Script Include.
# Red:
This is the function that asynchronously waits for a response. Any code that you need to wait for a response needs to go in the function referred to in the getXML(). Code that doesn't need to wait goes directly after the getXML() call inside the main Client Script function and won't wait for a response before executing.
# Cyan:
These are the pieces of data you need from the Server. They are added to an object in the Script Include and passed back to the Client Script. You can do anything with these when they are returned. In this example they are used to set a value on the form.
Client Side (Client Script):
function onChange(control, oldValue, newValue, isLoading) {
if (isLoading || newValue == '') {
return;
}
var ga = new GlideAjax('asu_GetLocationData');
ga.addParam('sysparm_name', 'getCampus');
ga.addParam('sysparm_buildingid', g_form.getValue("u_building"));
ga.getXML(updateCampus);
}
function updateCampus(response) {
var answer = response.responseXML.documentElement.getAttribute("answer");
var clearvalue; // Stays Undefined
if (answer) {
var returneddata = answer.evalJSON(true);
g_form.setValue("campus", returneddata.sys_id, returneddata.name);
} else {
g_form.setValue("campus", clearvalue);
}
}
Server Side (Script Include):
var asu_GetLocationData = Class.create();
asu_GetLocationData.prototype = Object.extendsObject(AbstractAjaxProcessor, {
getCampus: function () {
var buildingid = this.getParameter('sysparm_buildingid');
var loc = new GlideRecord('cmn_location');
if (loc.get(buildingid)) {
var campus = new GlideRecord('cmn_location');
if (campus.get(loc.parent)){
var json = new JSON();
var results = {
"sys_id": campus.getValue("sys_id"),
"name": campus.getValue("name")
};
return json.encode(results);
}
} else {
return null;
}
}
});
- 251,117 Views

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
getXMLAnswer will return the answer element from the XML response removing the need for the very clunky line:
var answer = response.responseXML.documentElement.getAttribute("answer");
No idea why people don't use this method more!
https://developer.servicenow.com/app.do#!/api_doc?v=jakarta&id=r_GLAX-getXMLAnswer_F

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi Shawn,
Very nicely done. I recall when I learning GlideAjax, the color coding really helped on the example I used. Thanks
I also recommend using JSON.stringify() instead json.encode() to do you encoding, and JSON.parse() instead of json.decode() as they is ECMAScript5 compliant and not a SN "version" of the same things. ES5 has been in place since Helsinki. If you're not there yet, here's another good reason to get up to date.

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Thanks! I've been meaning to update my example. This was based on a cheat sheet I created a few years ago for myself, so some of the code is outdated. Maybe I could have an ES3 version and an ES5 version for users pre and post Helsinki. There are other things I'd like to clean up in the example, but I need the time to test it before making changes to the script.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi, we are upgrading from Helsinki to Jakarta and are running into an issue with the GlideAjax script include. Similar to your example, we are looking for the campus based off the building. The campus keeps clearing which leads me to believe that the sys_id is not pulling correct. I'm not sure what changed from Helsinki to Jakarta that would cause issues.
Catalog Client Script
function onChange(control, oldValue, newValue, isLoading) {
if(isLoading)
return;
g_form.clearValue('room');
var ga = new GlideAjax('DataHelperAJAX');
ga.addParam('sysparm_name','singleSysid');
ga.addParam('sysparm_table','alm_building');
ga.addParam('building', g_form.getValue('building'));
ga.getXML(populateCampus);
function populateCampus(response) {
var answer = response.responseXML.documentElement.getAttribute("answer");
g_form.setValue('campus',answer);
}
}
Script Include
var DataHelperAJAX = Class.create();
DataHelperAJAX.prototype = Object.extendsObject(AbstractAjaxProcessor, {
singleSysid: function(){
var table = this.getParameter('table');
var building = this.getParameter('building');
var gr = new GlideRecord('alm_building');
gr.addQuery('sys_id', building);
gr.setLimit(1);
gr.setWorkflow(false);
gr.query();
if(gr.next()){
return gr.campus;
} else {
return '';
}
},
type: 'DataHelperAJAX'
});
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi heathers,
Looks like you need to change this line in your script include:
var table = this.getParameter('table');
This should be
var table = this.getParameter('sysparm_table');
That should fix it. Although it's best practice to pass the value and display name for a reference field as in the example above.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Thanks Shawn. This is really good info.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
HI ,
I have requirement like
1. form table is different and section table is different.
2. I have section in that section i have around 20 feilds.
3. when I change any of the field in that section pop should display with yes or no option.
4. current and previous value are also required.
5. when click on yes one specific catalog item should create with the old and new values updates in the section.
6. Catalog Item request item has to get created for validating old and new values. and workflow should trigger for approval.
7. After approving new value should update in the fields.

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
I might be wrong but I think it's because getXMLAnswer will cause the client to hang while it waits for the Answer, which could defeat the point of using GlideAjax in this instance.

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi Shawn,
Thank you for sharing. I followed your instructions, but it's not working for me.
My Server side script includes:
var DVTHRProfileAjax = Class.create();
DVTHRProfileAjax.prototype = Object.extendsObject(global.AbstractAjaxProcessor, {
getFieldValue: function() {
var subjectPerson = this.getParameter('subject_person');
var hrProfile = new GlideRecord('sn_hr_core_profile');
hrProfile.addQuery('user', subjectPerson);
hrProfile.query();
if(hrProfile.next()) {
var json = new JSON();
var results = {
"new_line_manager": hrProfile.getDisplayValue('user.manager'),
"cost_center_home": hrProfile.getDisplayValue('u_cost_center'),
"cost_center_host": hrProfile.getDisplayValue('u_cost_center_host'),
"department": hrProfile.getDisplayValue('user.department'),
"gbu_home": hrProfile.getDisplayValue('u_global_business_unit'),
"gbu_host": hrProfile.getDisplayValue('u_global_business_unit_host'),
"bu_home": hrProfile.getDisplayValue('u_business_unit'),
"bu_host": hrProfile.getDisplayValue('u_business_unit_host'),
"sub_bu_home": hrProfile.getDisplayValue('u_sub_business_unit'),
"sub_bu_host": hrProfile.getDisplayValue('u_sub_business_unit_host'),
"job_family_home": hrProfile.getDisplayValue('u_job_family'),
"job_family_host": hrProfile.getDisplayValue('u_job_family_host'),
"sub_job_family_home": hrProfile.getDisplayValue('u_sub_job_family'),
"sub_job_family_host": hrProfile.getDisplayValue('u_sub_job_family_host'),
"discipline_home": hrProfile.getDisplayValue('u_discipline'),
"discipline_host": hrProfile.getDisplayValue('u_discipline_host'),
"group_job_name": hrProfile.getDisplayValue('u_group_job_name'),
"group_job_host": hrProfile.getDisplayValue('u_group_job_name_host'),
"legal_entity_home": hrProfile.getDisplayValue('u_legal_employer'),
"legal_entity_host": hrProfile.getDisplayValue('u_legal_employer_host')
};
return json.encode(results);
}
},
type: 'DVTHRProfileAjax'
});
My onChange client script:
The issue is that answer is returned as null on the client side.
Could you help me check it?
Thank you.


- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hello,
Please use the forum tools as appropriate to organize your code. If you look at your post now, it's all slammed in to a wall of text and completely unreadable.
Please mark reply as Helpful, if applicable. Thanks!

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hello Allen,
I did. 🙂 thank you.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hello Oliver,
it looks like there are a few changes you need to make.
First of all, in your client script:
the function updateField(response) needs to be outside the onChange function. So you need a close bracket "}" on line 13 and remove the one on your last line.
I also recommend using getXMLAnswer() instead of getXML(). It saves you from having to parse the answer out in the callback function. See below:
function onChange(control, oldValue, newValue, isLoading) {
if (isLoading || newValue == '') {
return;
}
var ga = new GlideAjax('DVTHRProfileAjax');
ga.addParam('sysparm_name','getFieldValue');
ga.addParam('subject_person',g_form.getValue('subject_person'));
//ga.getXML(updateField);
ga.getXMLAnswer(updateField);
}
function updateField(response) {
//var answer = response.responseXML.documentElement.getAttribute('answer');
g_form.addInfoMessage(response);
}
The second issue in the Script include. As Chuck Tomasi had suggested, you really should be using JSON.stringify() and JSON.parse() instead of encode() and decode(). In fact, I believe that has been deprecated now which is why your Script include is not completing. You must remove the line
var json = new JSON();
There are two options to use JSON.stringify. You can keep your results object as defined and then use JSON.stringify(results) or you can just do it in one operation and return JSON.stringify({yourObjectData}).
Option1:
var DVTHRProfileAjax = Class.create();
DVTHRProfileAjax .prototype = Object.extendsObject(global.AbstractAjaxProcessor, {
getFieldValue: function() {
var subjectPerson = this.getParameter('subject_person');
var hrProfile = new GlideRecord('sn_hr_core_profile');
hrProfile.addQuery('user', subjectPerson);
hrProfile.query();
if (hrProfile.next()) {
//var json = new JSON();
var results = {
"new_line_manager": hrProfile.getDisplayValue('user.manager'),
"cost_center_home": hrProfile.getDisplayValue('u_cost_center'),
"cost_center_host": hrProfile.getDisplayValue('u_cost_center_host'),
"department": hrProfile.getDisplayValue('user.department'),
"gbu_home": hrProfile.getDisplayValue('u_global_business_unit'),
"gbu_host": hrProfile.getDisplayValue('u_global_business_unit_host'),
"bu_home": hrProfile.getDisplayValue('u_business_unit'),
"bu_host": hrProfile.getDisplayValue('u_business_unit_host'),
"sub_bu_home": hrProfile.getDisplayValue('u_sub_business_unit'),
"sub_bu_host": hrProfile.getDisplayValue('u_sub_business_unit_host'),
"job_family_home": hrProfile.getDisplayValue('u_job_family'),
"job_family_host": hrProfile.getDisplayValue('u_job_family_host'),
"sub_job_family_home": hrProfile.getDisplayValue('u_sub_job_family'),
"sub_job_family_host": hrProfile.getDisplayValue('u_sub_job_family_host'),
"discipline_home": hrProfile.getDisplayValue('u_discipline'),
"discipline_host": hrProfile.getDisplayValue('u_discipline_host'),
"group_job_name": hrProfile.getDisplayValue('u_group_job_name'),
"group_job_host": hrProfile.getDisplayValue('u_group_job_name_host'),
"legal_entity_home": hrProfile.getDisplayValue('u_legal_employer'),
"legal_entity_host": hrProfile.getDisplayValue('u_legal_employer_host')
};
//return json.encode(results);
return JSON.stringify(results);
}
},
type: 'DVTHRProfileAjax '
});
Option2:
if (hrProfile.next()) {
return JSON.stringify({
"new_line_manager": hrProfile.getDisplayValue('user.manager'),
"cost_center_home": hrProfile.getDisplayValue('u_cost_center'),
"cost_center_host": hrProfile.getDisplayValue('u_cost_center_host'),
"department": hrProfile.getDisplayValue('user.department'),
"gbu_home": hrProfile.getDisplayValue('u_global_business_unit'),
"gbu_host": hrProfile.getDisplayValue('u_global_business_unit_host'),
"bu_home": hrProfile.getDisplayValue('u_business_unit'),
"bu_host": hrProfile.getDisplayValue('u_business_unit_host'),
"sub_bu_home": hrProfile.getDisplayValue('u_sub_business_unit'),
"sub_bu_host": hrProfile.getDisplayValue('u_sub_business_unit_host'),
"job_family_home": hrProfile.getDisplayValue('u_job_family'),
"job_family_host": hrProfile.getDisplayValue('u_job_family_host'),
"sub_job_family_home": hrProfile.getDisplayValue('u_sub_job_family'),
"sub_job_family_host": hrProfile.getDisplayValue('u_sub_job_family_host'),
"discipline_home": hrProfile.getDisplayValue('u_discipline'),
"discipline_host": hrProfile.getDisplayValue('u_discipline_host'),
"group_job_name": hrProfile.getDisplayValue('u_group_job_name'),
"group_job_host": hrProfile.getDisplayValue('u_group_job_name_host'),
"legal_entity_home": hrProfile.getDisplayValue('u_legal_employer'),
"legal_entity_host": hrProfile.getDisplayValue('u_legal_employer_host')
});
}

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi Mohammad,
Quick note, getXMLAnswer will cause the browser to hang the same way that getXMLWait will, therefore it is not recommended unless you specifically need the browser to wait until the ajax response has been received before continuing to process your client side code.
Cheers
Francis C.

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
I finally created an updated version of this article trying to incorporate the comments here.

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
@Community Alums The screenshots don't match the text of the scripts pasted in the comment. I looked a the pasted text and didn't see anything that stuck out as wrong on first glance. I just wanted to make sure which scripts you are struggling with. Is it both?
I see you have an alert() in there. Does the alert() show any data? Have you tried debugging the Script Include? Is the sys_id making it to the server side? Is the Glide Record lookup returning the user data for that sys_id? You need to track down where the data isn't making it to the next step.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Client scripts:
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if (isLoading || newValue === '') {
return;
}
//Type appropriate comment here, and begin script below
var gal = new GlideAjax('CallerEmail');
gal.addParam("sysparm_name", "getDate");
gal.addParam("sysparm_userselected", g_form.getValue('u_caller_id'));
gal.getXMLAnswer(setDetails);
function setDetails(response) {
var userobj = JSON.parse(response);
g_form.setValue('u_email', userobj.email);
}
}
Script Include;
var CallerEmail = Class.create();
CallerEmail.prototype = Object.extendsObject(AbstractAjaxProcessor, {
getDate: function() {
var user = this.getParameter('sysparm_userselected');
var usr = new GlideRecord('sys_user');
usr.addQuery('sys_id', user);
usr.query();
if (usr.get(user)) {
var obj = {};
obj.email = usr.getDisplayValue('email');
}
return JSON.stringify(obj);
},
type: 'CallerEmail'
});
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
code is well explained but what is use case can anyone explain this code for what?
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hello @Shawn Dowler can you explain what the code is doing.
I mean what is the use case.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hello
I want to make an API call to an external application from Script Include. How to do this?
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Sharing this live example demo where I added a resuable class and made the AbastractAjaxProcessor become a base class to dynamically call parameters that can revceive any type of payload from the client towards the server side using GlideAjax.
Dynamic Script Include and GlideAjax in ServiceNow: Scalable & Reusable Code for Architects
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
I’ve put together a full playlist that walks through a complete “Build It the Right Way” scripting approach—showcasing object-oriented techniques, secure coding practices, and software design patterns to help you write clean, scalable, and production-ready code.