
- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
01-09-2020 09:49 PM - edited 08-03-2024 07:33 AM
Articles, Blogs, Videos, Podcasts, Share projects - Experiences from the field
Hi there,
Community questions on Client Side scripting to retrieve data, often answers are giving suggestions to use GlideAjax. GlideAjax (with getXMLAnswer) absolutely being the best method for retrieving data Client Side.
Though somehow a lot developers are using techniques like GlideRecord, getReference or getReference with a callback. Obviously, this could be because of someone is new in the ServiceNow eco-system and just hasn't touched on this subject yet. Or it could be the developer is just lazy 😀. Or could it be that answers and articles on the Community on this subject (and there are loads of them!) are not clear enough or hard to find?
Well, I'll give it a go to explain some basic GlideAjax examples (with getXMLAnswer). In a later article I'll explain our dynamic GlideAjax functionality. Also, I'll add some hints to make the scripting a lot easier.
Client Side Scripting
First, let's explain why GlideAjax is mentioned so often. Why not just use one (1) line of code with GlideRecord getReference? Or five (5) lines of code with GlideRecord? Those are so easy to set up, so why not?!
You might have seen the table below already somewhere (not mine: Paul Morris!). The table is a good visualization of Simplicity versus Efficiency.
API | Simplicity | Efficiency | Description |
GlideRecord getReference | 1st | 5th | - 1 line of code - Poor UX (blocks browser) - Returns entire record |
GlideRecord | 2nd | 4rd | - ~ 5 lines of code - Poor UX (blocks browser) - Returns entire record |
GlideRecord getReference (with callback) |
3rd | 3rd | - 5-10 lines of code (with callback) - Best UX (does not block browser) - Returns entire record |
GlideRecord (with callback) |
4th | 2nd | - ~ 10 lines of code (with callback) - Best UX (does not block browser) - Returns entire record |
GlideAjax | 5th | 1st | - ~20 lines of code (Client Script + Script Include) - Best UX (does not block browser) - Returns only the data you need |
Bad Practice
Looking at the above table, GlideRecord getReference, and GlideRecord are for sure not done. No explanation needed. Yes, one (line) of code could do, though efficiency-wise a really poor choice. Just don't go this road.
Poor Practice
Looking at the above table, GlideRecord getReference (with callback), and GlideRecord (with callback) are UX wise fine. Though, these still return the entire record. getRefence (with callback) is used a lot, though there is a better way.
Best practice
GlideAjax tops the efficiency chart. Make a habit of using this. So why is GlideAjax actually often not a habit to use? Well simply because developers are not familiar with this, that it takes a lot more lines of code instead of the really simple GlideRecord getReference, that it takes two (2) artifacts (a (Catalog) Client Script, and a Script Include).
Note: Actually I would change "GlideAjax" into "GlideAjax (with getXMLAnswer)". GlideAjax with getXML still would return a whole document. While GlideAjax with getXMLAnswer would only return the exact answer you need. Read about this in one of my previous articles: getXMLAnswer vs getXML.
Later in this article I'll give two (2) hints on how to make life for you as a developer easier, not having to write out all the code over and over. Also in a later article, I'll share our dynamic GlideAjax set up which can potentially be used on every field on every table through your instance without additional maintenance.
GlideAjax examples
1) We would like to retrieve the Phone number of a Caller selected. Phone number should be written to a custom Phone number field on the Incident form (u_phone).
Script Include
Name: getUserPropertiesAjax
Client callable: true
Script:
var getUserPropertiesAjax = Class.create();
getUserPropertiesAjax.prototype = Object.extendsObject(AbstractAjaxProcessor, {
get_phone : function() {
var grUser = new GlideRecord('sys_user');
if(grUser.get(this.getParameter('sysparm_user'))) {
return grUser.getValue('phone');
}
},
type: 'getUserPropertiesAjax'
});
Client Script
Table: Incident
Type: onChange
Field name: Caller
Script:
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if(isLoading) {
return;
}
if(newValue === '') {
g_form.clearValue('u_phone');
}
var gaPhone = new GlideAjax('getUserPropertiesAjax');
gaPhone.addParam('sysparm_name', 'get_phone');
gaPhone.addParam('sysparm_user', newValue);
gaPhone.getXMLAnswer(_handleResponse);
function _handleResponse(response) {
var answer = response;
g_form.setValue('u_phone', answer);
}
}
2) We would like to retrieve the Location of a Caller selected. Location should be written to the out-of-the-box Location field on the Incident form (location).
Script Include
We'll just add a function "get_location" to the Script Include created earlier.
Script:
var getUserPropertiesAJAX = Class.create();
getUserPropertiesAJAX.prototype = Object.extendsObject(AbstractAjaxProcessor, {
get_phone : function() {
var grUser = new GlideRecord('sys_user');
if(grUser.get(this.getParameter('sysparm_user'))) {
return grUser.getValue('phone');
}
},
get_location : function() {
var grUser = new GlideRecord('sys_user');
if(grUser.get(this.getParameter('sysparm_user'))) {
var answer = {};
answer.value = grUser.getValue('location');
answer.displayValue = grUser.getDisplayValue('location');
return JSON.stringify(answer);
}
},
type: 'getUserPropertiesAJAX'
});
Note: Instead of just returning "return grUser.getValue('location')", we are actually returning the getValue and the getDisplayValue. This is because g_form.setValue(), for a Reference field expects the value AND the display value. If only returning the value (the sys_id), an additional Server call will be performed (and the efficiency reason for why performing GlideAjax would then actually be lost).
Client Script
Table: Incident
Type: onChange
Field name: Caller
Script:
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if(isLoading) {
return;
}
if(newValue === '') {
g_form.clearValue('location');
}
var gaLocation = new GlideAjax('getUserPropertiesAJAX');
gaLocation.addParam('sysparm_name', 'get_location');
gaLocation.addParam('sysparm_user', newValue);
gaLocation.getXMLAnswer(_handleResponse);
function _handleResponse(response) {
var answer = JSON.parse(response);
g_form.setValue('location', answer.value, answer.displayValue);
}
}
Note: When using the Script Editor, notice the information on g_form.setValue:
Making life easier
So is there anything we can do about the downside of going for the top-ranked efficiency, which actually brings bottom-ranked simplicity?
1) Set up example (Catalog) Client Scripts
Client Scripts which you could simply "Insert and Stay", and modify. No need to write all the code out again.
2) Syntax Editor Macros
Write example GlideAjax call ones and save it in a Syntax Editor Macro. Syntax Editor Macros can easily be called within a Script field. Read about this in one of my previous articles: Expanding Syntax Editor Macros.
Dynamic GlideAjax
You might already notice, the functions in the Script Include can be used over and over, nice. Though for example, if you would now like to get your hands on the Email value of the User record, you would have to add a function again.
This can be done easier 🙂 I will share a Dynamic usage of GlideAjax in a future Community Article.
Platform UI, Service Portal / Client Script, Catalog Client Script
The usages of GlideAjax and the Script Include and Catalog Client Script, do work both for Platform UI and Service Portal. As example, I simply used the Incident form on the Platform UI, and therefor a Client Script. Using the exact same Script Include and GlideAjax scripting within Catalog Client Scripts should work fine.
---
And that's it actually. Hope you like it. If any questions or remarks, let me know!
C |
If this content helped you, I would appreciate it if you hit bookmark or mark it as helpful.
Interested in more Articles, Blogs, Videos, Podcasts, Share projects I shared/participated in? |
Kind regards,
Mark Roethof
ServiceNow Technical Consultant @ Quint Technology
---
- 63,629 Views

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
I can't believe that "Simplicity vs Efficiency" table I wrote up 4 years ago on a random thread is still making the rounds! I thought it looked familiar!
Nice article by the way 🙂
Since then I've re-written my own getReference() on Share that:
- Returns only the field data you need
- Returns display values
- Doesn't block the browser
FYI, the Expanding Syntax Editor Macros link in 2) Syntax Editor Macros is broken.

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi Paul,
Fixed the link, tnx.
The table is just... it almost says it all in my opinion and after some years still valid, I would only add using getXMLAnswer to it instead of getXML. I also mentioned your name for that. Will have a look at the SmartAjax, now I'm curious 🙂

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
I wasn't even sure if I made it but it sure looked familiar!
I looked back through my posts and found it from 4 years ago - lol
No sweat!
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Nice writeup Mark, thanks for all the content!
I'm a fan of the table API as another option for common use-cases
I made a short video with a related comparison a while back

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Great info Mark. Thanks!
Another resource is Episode 5 of TechNow (Client Scripting Fundamentals)
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi Mark
Thanks for your response. I need some more help as I am not used to this scripting.
Where do I put this script in my form?
What I am doing is this:
Maintain Items - I have variables, one is Employee and one is old_location (I need to get current location of employee in this field). Then I have one more variable - new_location, which end user can select from list.
so, where do I put your script?
Do I put in Catalog Client Script - OnChange for Employee field?
From your response, I think I need to put this on OnChange Catalog Client script:
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if(isLoading) {
return;
}
var galocation = new GlideAjax('getUserPropertiesAjax');
galocation.addParam('sysparm_name', 'get_location');
galocation.addParam('sysparm_user', newValue);
galocation.getXMLAnswer(_handleResponse);
function _handleResponse(response) {
var answer = response;
g_form.setValue('old_location', answer);
}
}
Where do I then put the below get_location script?
var getUserPropertiesAjax = Class.create();
getUserPropertiesAjax.prototype = Object.extendsObject(AbstractAjaxProcessor, {
get_location : function() {
gs.info(this.getParameter('sysparm_user'));
var grUser = new GlideRecord('sys_user');
if(grUser.get(this.getParameter('sysparm_user'))) {
return grUser.getValue('location');
}
},
type: 'getUserPropertiesAjax'
});
Regards,
Ashish Shah
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi
I am getting error" There is a javascript error on your browser console" when I am using your script for displaying Location of the employee selected
OnChange of employee field:
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if(isLoading) {
return;
}
if(newValue === '') {
g_form.clearValue('old_location');
}
var gaPhone = new GlideAjax('getUserPropertiesAjax');
gaPhone.addParam('sysparm_name', 'get_location');
gaPhone.addParam('sysparm_user', newValue);
gaPhone.getXMLAnswer(_handleResponse);
function _handleResponse(response) {
var answer = response;
g_form.setValue('old_location', answer);
}
}
in Include script:
var UserDetailsAjax = Class.create();
UserDetailsAjax.prototype = Object.extendsObject(AbstractAjaxProcessor, {
getUserDetails: function(){
var obj = {};
var gr= new GlideRecord('sys_user');
gr.get(this.getParameter('sysparm_user_id'));
obj.location=gr.getValue('location');
var json = new JSON();
var data = json.encode(obj);//JSON formatted string
return data;
},
type: 'UserDetailsAjax'
});
Can you let me know what I am doing wrong
regards,
Ashish Shah

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi there,
Post you question as a topic on the Community, this way you will get help/answers quicker.
If I do look at your last post. First thing that I notifce in your Script Include:
sysparm_user_id
This is not what you entered in your Client Script. So at least this is a mismatch. Possibly more, though at least this.
Kind regards,
Mark
2020 ServiceNow Community MVP
2020 ServiceNow Developer MVP
---
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi Mark
What should I have used instead of sysparam_user_id?
Should I use the field on which I am using OnChange? my field name is employee
I tried with this, but still does not work
Regards,
Ashish

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
in your client script you have to use "sysparam_user_id" not "sysparm_user"
gaPhone.addParam('sysparam_user_id', newValue);
if you are new to glide ajax, i would suggest go with official doc for better clarification.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi Mark
I think I am very close to getting this working
My Client script is as follows: onChange of employee field
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if(isLoading) {
return;
}
var galocation = new GlideAjax('UserDetailsAjax');
galocation.addParam('sysparm_name', 'UserDetailsAjax');
galocation.addParam('sysparm_user_id', newValue);
galocation.getXML(_handleResponse);
function _handleResponse(response) {
var answer = response.responseXML.documentElement.getAttribute("answer");
alert(answer);
g_form.setValue('remarks', answer);
}
}
My Include script is as follows:
var UserDetailsAjax = Class.create();
UserDetailsAjax.prototype = Object.extendsObject(AbstractAjaxProcessor, {
UserDetailsAjax: function(){
var obj = {};
var gr= new GlideRecord('sys_user');
gr.get(this.getParameter('sysparm_user_id'));
obj.email = gr.getValue('email');
obj.location=gr.getValue('location');
var json = new JSON();
var data = json.encode(obj);//JSON formatted string
return data;
},
type: 'UserDetailsAjax'
});
So, when I run this, I am getting output from alert(answer) as:
{"email":"Ashish.Shah@ipsos.com","location":"d1c6d5ba371f9200d38bd1b543990e9e"}
So, I am getting the 2 values Email and Location.
How do I get them in separate variables so that I can use SetValue to set 1 field?
I tried g_form.setValue('remarks', answer.email) -- but does not work
Kindly suggest on this part ahead
Regards,
Ashish Shah

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
try now
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if(isLoading) {
return;
}
var galocation = new GlideAjax('UserDetailsAjax');
galocation.addParam('sysparm_name', 'UserDetailsAjax');
galocation.addParam('sysparm_user_id', newValue);
galocation.getXML(_handleResponse);
function _handleResponse(response) {
var answer = response.responseXML.documentElement.getAttribute("answer");
var ab = JSON.parse(answer);
g_form.setValue('remarks', ab.email);
}
}
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Thanks Harsh. This worked for me
Regards,
Ashish
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Thanks Mark for all the help.
It is working fine at my end now
regards,
Ashish
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
return grUser.getValue('phone');
here we have to write
'u_mobile_number' as in my incident iam not getting the desired output
and in empty box it has to display mobile number
how to write script for this...anybody please help me...

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi Veena,
Please post the script you tried here. So that will be easy to guide you. Thanks.
Regards,
Hari
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi, Mark is it also possible in OnLoad Client Script?

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi there,
onLoad Client Script, wouldn't scratchpad be better in that case? Or do you mean Catalog Client Script?
Kind regards,
Mark
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
If you are writing an 'onSubmit' client script with GlideAjax, it's ideal to use a getXMLWait() method followed by getAnswer().
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
In many cases I do use GlideAjax with getXMLAnswer but there are also several places where I use a default value of:
javascript:gs.getUser().getEmail();
or
javascript:'u_building_name=' + current.variables.v_building; // where reference is to a custom Rooms table with a column called u_building_name
I see I can now use auto-populate to replace the second example (yayy!). Are these examples inefficient and bad UX too?
And thanks very much for this post!
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Good information and a nice explanation with best practices.