Glide Ajax - ServiceNow
Paul Stuart
ServiceNow | CIS-CSA | CIS-ITSM | CIS-HRSD | ITIL-4 | Integrations | JavaScript |
Article accompanying video on how to use Glide Ajax in ServiceNow.
In my last post I demonstrated how Glide Ajax can be very handy when you want to quickly and easily retrieve server-side data on client-side forms, such as a standard Incident form.
If a form does not have direct access to another table in the related lists, or form layout configuration, then using Glide Ajax you do a Glide Record Query from a server side script and pull in any requested data. A good way to think about it would be; the server-side is a chef in the kitchen. The client-side is a customer at the restaurant, and Glide Ajax is the waiter.
I started off by showing how I constructed my Script Include, note that I have two functions, however for the demonstration I am only concerned with the one handling RITMs.
Notice how with my script include I have extended the AbstractAjaxProcessor class. This is handy, and an out of the box class from ServiceNow, as now I can simply let that abstract class to the heavy lifting of handling the request to the server, and I can focus on my logic.
When you use Glide Ajax you always have to use the prefix 'sysparm_' then the field name you would normally use in any other ServiceNow API.
var UserUtils = Class.create();
UserUtils.prototype = Object.extendsObject(AbstractAjaxProcessor, {
getUserDetails: function(userID) {
userID = this.getParameter('sysparm_userID') || userID;
gs.log("The User ID is: " + userID, 'UserUtils');
var userObj = {};
var userGr = new GlideRecord('sys_user');
if (userGr.get(userID)) {
userObj.manager = userGr.getDisplayValue('manager');
userObj.managerV = userGr.getValue('manager');
userObj.email = userGr.getDisplayValue('email');
userObj.emailV = userGr.getValue('email');
userObj.mobile = userGr.getDisplayValue('mobile_phone');
userObj.mobileV = userGr.getValue('mobile_phone');
userObj.title = userGr.getDisplayValue('title');
userObj.titleV = userGr.getValue('title');
userObj.department = userGr.getDisplayValue('department');
userObj.departmentV = userGr.getValue('department');
userObj.location = userGr.getDisplayValue('location');
userObj.locationV = userGr.getValue('location');
}
return JSON.stringify(userObj);
},
getUserReqItems: function(userId) {
userId = this.getParameter('sysparm_userID') || userId;
var reqItems = [];
var ritmGr = new GlideRecord('sc_req_item');
ritmGr.get('requested_for', userId);
while (ritmGr.next()) {
reqItems.push({
"number": ritmGr.number.toString(),
"Due Date": ritmGr.due_date.toString(),
"Stage": ritmGr.stage.toString(),
"Description" : ritmGr.description.toString()
});
gs.log("Number RITM : " + ritmGr.number + ", Due Date: " + ritmGr.due_date);
gs.log("Short Description : " + ritmGr.cat_item.short_description);
gs.log("Description : " + ritmGr.cat_item.description + "\n");
}
return JSON.stringify(reqItems);
},
type: 'UserUtils'
});
Notice in my getUserReqItems function, its important to use the JavaScript .toString() function so that way, it converts the value from a GlideRecord value into a standard string. This is because I needed to then use the JSON.stringify function, which can only interpret strings. It won't understand what a GlideRecord is so it will simply return null if you don't convert it.
领英推è
For the client-side, I have used the incident table, on-change, and the field name is Caller.
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if (isLoading || newValue === '') {
return;
}
g_form.clearMessages();
var userUtils = new GlideAjax('global.UserUtils');
userUtils.addParam('sysparm_name', 'getUserReqItems');
userUtils.addParam('sysparm_userID', newValue);
userUtils.getXMLAnswer(function(response) {
var ritmArray = JSON.parse(response);
if (ritmArray.length > 0) {
for (var i = 0; i < ritmArray.length; i++) {
var firstObj = ritmArray[i];
g_form.addFormMessage("RITM Number: " + firstObj.number + ", Description: " + firstObj.Description + ", Due Date: " + firstObj['Due Date'] + ", Stage: " + firstObj.Stage, "warning");
}
} else {
g_form.addErrorMessage("The RITM array is NOT greater than 0");
}
});
}
You can see Glide Ajax being instantiated on the client script, again as well as on server side, you must pass in your parameters with the prefix (sysparm_) mention earlier. The Script Include is being called, then using the addParam function I can specify the function that I need to call, and finally I can specify the parameter being passed in from the client to the script include. Which is; 'userID'.
Also important, now on the client side, we must use JSON.parse() function to interpret the client data that I previously had to convert using JSON.stringify().
Now every time you switch users in the caller field on the Incident form, it will run this ajax call and update the screen instantly to give a smoother user experience, instead of waiting for the page to reload.
If a user has no RITMs associated with their user profile then an error message will show up.
A note of caution with this approach, note that although quite neat and impressive to see in action, use with discretion and be mindful of both the technical overhead it would incur for the customer. And secondly, how much data is being pulled each time. For example, in my demonstration, it was only a handful of RITMs with a few fields. What if the users had 1-200 RITMS attached to each of their names? How would that affect performance? Is there a better solution?
However, for the purpose of understanding the logic, this is a good demonstration to try.
ServiceNow Architect & Mentor | 4x MVP (2022-24) | Author of "Think Thrice Code Once" | Certified CTA, CIS, CAD, CSA | ITSM & Agile Expert | Empowering Professionals Through Technomonk
1 å¹´Great demonstration! I'm excited to learn how to use Glide Ajax in ServiceNow. Thanks for sharing!