The Now Platform® Washington DC release is live. Watch now!
on 09-20-2020 06:04 AM
For those of you that are not familiar with GlideAjax. getXMLWait() is a Synchronous GlideAjax call. Meaning your script cannot continue without the GlideAjax response. This stops the session until the response is received.
If we look at a scripting example. Lets say we want to do some checks onSubmit of a Catalog item. In our case, we want to validate the user is part of a company. If the user is not part of the company, we want to abort the Catalog Item request and show an error message. To do this, we can use a Script Include to handle the Server lookup and an onSubmit Catalog Client script that prevents submission. We do not want to continue submission until we get a response from the Server back, stating it is alright.
To do this we can write the following Client Callable script include. If you want to do a different validation, you can change it.
var catItemHelper = Class.create();
catItemHelper.prototype = Object.extendsObject(AbstractAjaxProcessor, {
checkCompany: function () {
var answer = false;
var user = this.getParameter('sysparm_user');
var gr = new GlideRecord('sys_user');
gr.addQuery('sys_id', user);
gr.addQuery('company.name', "ACME North America");
gr.query();
if (gr.next()) {
answer = true;
}
return answer;
},
type: 'catItemHelper'
});
As an onSubmit client script we have the following script:
function onSubmit() {
var user = g_user.userID;
var ga = new GlideAjax('catItemHelper'); //Name of the Script Include
ga.addParam('sysparm_name', 'checkCompany'); //name of function in script include
ga.addParam('sysparm_user', user);
ga.getXMLWait();
var answer = ga.getAnswer();
if (answer == 'false') {
g_form.addErrorMessage('Only users from company ACME North America are allowed');
return false;
}
}
User has company "ACME North America":
User does not have company "ACME North America":
getXMLWait() is not supported by the Service Portal:
When we try the same item in the Service Portal we get the following:
In the console:
To prevent the error from appearing we can set our Client Script as UI Type Desktop. Because that is where the script is working:
We do not get the popup anymore, but the validation is also not happening anymore on the Service Portal.
In the Service Portal Asynchronous Ajax calls are supported.
The issue with these Asynchronous Ajax calls however, is that the script will not wait for the Server response. Meaning the Catalog Item will continue to be submitted, before we have a response back from the Server. So the validation we want will not work.
When the user clicks the submit button, we can return false, which will stop submission. We also trigger the Ajax call to the server. In the Callback function that handles the response (asynchronous) we can trigger the Submit from script again. But this time, if the response from the Server is not false, we set g_scratchpad.isFormValid to true. Which results in the script returning true and allowing us to submit the item.
To do this we add the following onSubmit Catalog Client Script. UI Type: Mobile/Service Portal:
function onSubmit() {
if (g_scratchpad.isFormValid)
return true;
var user = g_user.userID;
var ga = new GlideAjax('catItemHelper'); //Name of the Script Include
ga.addParam('sysparm_name', 'checkCompany'); //name of function in script include
ga.addParam('sysparm_user', user);
ga.getXMLAnswer(setAnswer);
return false;
function setAnswer(answer) {
if (answer == 'false') {
g_form.addErrorMessage('Only users from company ACME North America are allowed');
return false;
}
var actionName = g_form.getActionName();
g_scratchpad.isFormValid = true;
g_form.submit(actionName);
}
}
User has company "ACME North America":
User does not have company "ACME North America":
Thank you! Feel free to bookmark and share with others! 🙂
Wonderful article... Saved my life...
Hahaha glad my article helped save your life! 🙂
Nice workaround! Great job, really helped me out there.
Hi Willen,
I was just wondering if its possible to show a processing image or something until the get XML response is returned? This is because form is not doing anything until the response is returned and users might get an impression that nothing is happening.
Hi Willem,
I like this solution! Thanks!
Hi Willem,
good solution as I also experienced the getXMLWait not working. This is a very useful workaround.
Very clever little workaround.
The best workaround I found to replace the using of getXMLWait on scoped applications. Thanks!
If someone is looking for official documentation please refer Knowledge Article reference from ServiceNow KB0783579
Very helpful:)
Very helpful.
But how can we return more than one value from Script include in this case
You can for example return an object from your script include. Adjust the Client script accordingly:
In below example the Server returns an object. One of the properties in that object is pass (or you can name it whichever you like).
So:
var obj = {
pass: true,
second_value: "your value",
third_value: "your other value"
}
Then in the client script you check if answer.pass
function onSubmit() {
if (g_scratchpad.isFormValid)
return true;
var user = g_user.userID;
var ga = new GlideAjax('catItemHelper'); //Name of the Script Include
ga.addParam('sysparm_name', 'checkCompany'); //name of function in script include
ga.addParam('sysparm_user', user);
ga.getXMLAnswer(setAnswer);
return false;
function setAnswer(answer) {
var answerObj = JSON.parse(answer);
if (answerObj.pass == 'false') {
g_form.addErrorMessage('Only users from company ACME North America are allowed');
return false;
}
var actionName = g_form.getActionName();
g_scratchpad.isFormValid = true;
g_form.submit(actionName);
}
}
Hope this helps! 🙂
(If so mark helpful and the article as well! :D)
Thank you for your quick response
but its not working
It is giving error like "There is a JavaScript error in your browser console"
Can you share the error you get?
onSubmit client script is as follow
function onSubmit() {
if (g_scratchpad.isFormValid)
return true;
if ((g_form.getValue("please_select_one_of_the_below_options") == " Incident") ) {
var ga = new GlideAjax('ValidateINC');
ga.addParam('sysparm_name', 'checkIncident');
ga.addParam('sysparm_user', g_form.getValue('incident_ticket'));
ga.getXMLAnswer(setAnswer);
return false;
}
}
function setAnswer(answer) {
var answerObj = JSON.parse(answer);
if (answerObj.pass == 'false') {
g_form.addErrorMessage('Incident Ticket ' + answerObj.esc + ' is already created for the issue');
return false;
}
}
var actionName = g_form.getActionName();
g_scratchpad.isFormValid = true;
g_form.submit(actionName);
Script include is as follow
var ValidateINC= Class.create();
ValidateINC.prototype = Object.extendsObject(AbstractAjaxProcessor, {
checkIncident: function() {
var answer = true;
var inc = this.getParameter('sysparm_user');
var gr = new GlideRecord('table_name');
gr.addQuery('u_reference_1.sys_id', inc);// u_reference_1 is field on table_name table
gr.query();
if (gr.next()) {
var obj = {
pass: false,
esc: gr.getValue("number")
};
}
return answer;
},
type: 'ValidateINC'
});
still getting same error
Hi ,
Please let me know what solution you have used to show a processing image or something until the get XML response is returned?
I am also facing same issue when we click Submit for a record producer , form is not doing anything until the response is returned
2 options:
1. put everything in a JSON object, stringify it in script include before return and JSON.parse in client script side.
2. Use json.encoding : https://community.servicenow.com/community?id=community_question&sys_id=b1a2d7a1db101fc01dcaf3231f961927
Hi Team,
My onSubmit client script not working on service portal
I have catalog item where user will be selecting a group name ,
And if the current logged in user is the group manager of the user selected group then user should be able to place the request if not we should restrict the user from placing order.
Below is my code
CLIENT SCRIPT
function onSubmit() {
if (g_scratchpad.isFormValid)
{
return true;
}
var user = g_user.userID;
var group = g_form.getValue('group_name');
alert(group);
var gajax = new GlideAjax('TESTMANAGER'); // replace your script include name here
gajax.addParam('sysparm_name','isManager'); // replace function name here
gajax.addParam('sysparm_group',g_form.getValue('group_name'));
gajax.addParam('sysparm_user',user);
gajax.getXMLAnswer(setAnswer);
return false;
function setAnswer(answer) {
if (answer == 'false') {
alert(answer);
g_form.addErrorMessage('Only group managers can place a request');
return false;
}
alert('true');
var actionName = g_form.getActionName();
g_scratchpad.isFormValid = true;
g_form.submit(actionName);
}
}
SCRIPT INCLUDE
var TESTMANAGER = Class.create();
TESTMANAGER.prototype = Object.extendsObject(AbstractAjaxProcessor, {
isManager: function() {
var answer=false;
var user = this.getParameter('sysparm_user');
var group = this.getParameter('sysparm_group');
var grGroup = new GlideRecord('sys_user_group');
grGroup.addQuery('sys_id',group);
grGroup.addQuery('manager',user);
grGroup.query();
if(grGroup.next()) {
answer =true;
}
return answer;
},
type: 'TESTMANAGER'
});
-->Whenever group manager matches with the current logged- in user, I 'am getting the alerts and form is submitted as expected,But when they does not match I 'am not even receiving the alert statements.
-->And when I 'am selecting group manager different from the current logged -in user for the first time when form loads then it works as expected(only first i.e., when form loads, and when the values are changed same as usual no alerts and form is submitted.
Please suggest and help
Thanks in Advance
You are a genius! 🙂
Thanks for help..
Very smart, and nicely described; Thank you. However...
I kind of HATE that this is necessary, and I can see this being pretty confusing for someone who comes after you.
It seems like ServiceNow is terrified of synchronous calls to the server, and is bending over backwards to prevent anyone from doing anything which could "block" the client, even for a few milliseconds. I don't know why they are doing that. Were there horrible problems with this in the past?
What you have shown seems like a valid use-case.
Because ServiceNow hasn't provided a standard method for doing this type of synchronous action, now we are in a game of Cat and Mouse, where ServiceNow tries to prevent its customers from doing something, and then their customers invent new ways (like this) of doing it.
I was stuck for over 2 hours trying to find a solution, your article solved it perfectly.
Thank you very much! 😀
Hi,
Not sure if it's dependent on version but on Quebec if answer function return true i need to click again on submit button because actionName variable return "none". I fix it by putting 'submit' in g_form.submit() function.
g_scratchpad.isFormValid = true;
g_form.submit('submit');
Hey,
Thanks for this article. I have used the same approach for one of my requirement.
Just wanted to confirm, Whether it comes under best practice of servicenow or not? OR it has any other impacts?
Regards,
Kartik
Thank you! Great explanation!
@Will
This guy @amitgujarathi is using your content but not giving credit. Besides, he is claiming as his! This is very unfair. This is plagiarism!!!
Hi, i don't know if this thread is still active but here's an issue that I encountered:
The script successfully blocks submission when the Ajax returns false. However, when I change the value to true and submit the form again, the console will continuously throw this warning (over 1000 times) and never submit it.
Overwriting extension point: g_validation_script_field_count
Does anyone know how to solve this issue and why this is a thing?
Hi Willem,
i know it's been a while , but this method doesn't work with Multirow variable set.
do you have any idea how should i approach this , as i want to add delay.
Regards,
Varun Sharma
So, I didn't see it mentioned, but why was xmlwait removed in the first place. I just did a look at the base code and ServiceNow still uses it (in Global) in 39 client scripts. So the question: why get rid of an important and valuable tool in the platform? BTW, it solves the very problem that was brought up as an example in this article (nice job btw on the workaround Willem).
getXMLWait() can't be used in Configurable Workspace either.
This method is really helpful for simple client script. But my question is how can we use this method in Catalog Client Script, because we cannot use g_form.Submit and g_scratchpad in catalog client script.
Hi @Willem,
great piece of code. I have one question: why do you use your code for Portal only? It should not work in Desktop also, saving us to use two client scripts?
Regards,
Pablo Espinar
Hello @Willem
I have followed the solution which you have provided it's working as expected but one thing I am getting one error like when user clicks on submit button in portal to submit the request first time the submission is not happening and when we click on again submit button that time it's gets submitted.
Could please suggest me it's need to submit at first time user clicks on submit button..
Regards,
Haresh
hi @Haresh Haru,
try this one
Not sure if it's dependent on version but on Quebec if answer function return true i need to click again on submit button because actionName variable return "none". I fixed it by putting 'submit' in g_form.submit() function.
g_scratchpad.isFormValid = true; g_form.submit('submit');
Hello @Kamil Smusz
Can you please tell me in this client script i have put this code but it's not working as expected it's submitted without validation the condition..
hi @Haresh Haru
looks like you need to comment 2 lines like below
function setAnswer(answer) {
//alert(answer);
if (answer == true) {
g_form.addErrorMessage('The guest user already exists in the user table');
return false;
}
//var actionName = g_form.getActionName();
g_scratchpad.isFormValid = true;
//g_form.submit(actionName);
g_form.submit('submit');
Hello @Kamil Smusz
I have commented out and I tried also but it's not working like it's throwing when condition meet but it's not submitting if I click on several times
hi @Haresh Haru,
Have you checked if you if function is working? Can you show me what you returning in Script Include ?
Hello @Kamil Smusz
Please find my script include and client script aswell and help me on this ..
Script include :
hi @Haresh Haru
please update your script include like below
if (user.next()) {
return 'true';
}
else return 'false';
Hello @Kamil Smusz
Awesome, Now it's working as expected thanks a lot for your support.
Regards,
Haresh