The CreatorCon Call for Content is officially open! Get started here.

Willem
Giga Sage
Giga Sage

Get XML wait

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.

How to use getXMLWait

Scenario

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.

 

The script

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;
    }
}

 

The result

User has company "ACME North America":

find_real_file.png

 

 

User does not have company "ACME North America":

find_real_file.png

The issue

getXMLWait() is not supported by the Service Portal:

https://docs.servicenow.com/bundle/orlando-servicenow-platform/page/build/service-portal/reference/c...

 

When we try the same item in the Service Portal we get the following:

find_real_file.png

 

In the console:

find_real_file.png

To prevent the error from appearing we can set our Client Script as UI Type Desktop. Because that is where the script is working:

find_real_file.png

 

We do not get the popup anymore, but the validation is also not happening anymore on the Service Portal.

 

Asynchronous Ajax call

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.

 

The solution

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);

    }
}

 

The result

User has company "ACME North America":

find_real_file.png

 

User does not have company "ACME North America":

find_real_file.png

 

Comments
arunkumar119909
Tera Contributor

Hi Team,

 

 i am used below on submit client script(Catalog iteam )

using that script one instance it's working fine and other instance its showing bellow error. If any one know this kind of issue na could pls help me on this

 

Error MessageonSubmit script error: ReferenceError: g_scratchpad is not defined:
function () { [native code] }

 

function onSubmit() {
    //Type appropriate comment here, and begin script below

    if (g_scratchpad.validForm) {
        return;
    }


    var partner = g_form.getValue('select_partner');
    var segment = g_form.getValue('segment_lead');

    var mrvs = g_form.getValue('itinerary');

    var vk = new GlideAjax("Decision_table_risk_rating");
    vk.addParam('sysparm_name', 'getriskratings');
    vk.addParam('sysparm_from', g_form.getValue('from_originating_country'));
    vk.addParam('sysparam_to', g_form.getValue('to_destination_country'));
    vk.addParam('sysparam_mrvs', mrvs);

    vk.getXML(function risk(response) {

        var answer = response.responseXML.documentElement.getAttribute("answer");
        alert('risk_rating' + answer);
        g_form.setValue('risk_rating', answer);
        if (answer == 1 && partner == '' && segment == '') {
            g_form.setVisible('partner', true);
            g_form.setVisible('segment', true);
            g_form.setMandatory('partner', true);
            g_form.setMandatory('segment', true);
            g_scratchpad.validForm = false;
        } else {
            g_scratchpad.validForm = true;
            g_form.submit();
        }
    });

    // vk.getXMLWait();

    // var answer = vk.getAnswer();
    // aler('risk rating ==' + answer);

    // g_form.setValue('risk_rating', answer);

    // if (answer == 1 && partner == '' && segment == '') {
    //     g_form.setVisible('partner', true);
    //     g_form.setVisible('segment', true);
    //     g_form.setMandatory('partner', true);
    //     g_form.setMandatory('segment', true);
    //     return false;
    // } else {
    //     return true;
    // }





}
mahesh baghel
Tera Contributor

@Willem , i am getting the error when creating tickets from ServiceNow platform 

 

error is : "onSubmit script error: ReferenceError: g_scratchpad is not defined:
function () { [native code] } "

but in the Service Portal it's working fine.

May I know the full on-submit client script which can work in ServiceNow Platform and SP also.

Mishu
Tera Expert

@Willem -  Can you please help me with almost a similar query, please

https://www.servicenow.com/community/developer-forum/logged-in-user-should-be-a-part-of-a-group-then...

 

I have tagged you in the same post

ya1988bk
Tera Contributor

Your amazing solution just help me to create onSubmit Catalog Client Script that prevents submission if the incident for the item has already been reported by others (for example, during outage).

Below is the template for the onSubmit Catalog Client Script

 

function onSubmit() {
   if (g_scratchpad.isFormValid)
		return true;
  // Gets sys_id for Ref and Display Value for non-Ref fields   

   var field1 = g_form.getValue('field1'); // e.g. printer name
   var field2 = g_form.getValue('field2'); // e,g, category - hardware issue
   var field3 = g_form.getValue('field3'); // e.g. issue - out of ink

   var callToScriptIncludeGA = new GlideAjax('ExistingIncidentFinder'); // Calls Script Include by its Name
   callToScriptIncludeGA.addParam('sysparm_name', 'findExistingIncident'); // Calls the function within Script Include
   callToScriptIncludeGA.addParam('sysparm_field1', field1);
   callToScriptIncludeGA.addParam('sysparm_field2', field2);
   callToScriptIncludeGA.addParam('sysparm_field3', field3);
   callToScriptIncludeGA.getXMLAnswer(responseFromGlideAjax);
   return false; // This stops Catalog Client Script execution until response received from GlideAjax

   function responseFromGlideAjax(answer) {
		if (answer) { // If there an answer from GlideAjex thus the case already exists
			g_form.addErrorMessage(answer) // This is 'message' variable from the Client Script
			return false; // This stops Catalog Client Script execution completely			
		}

		g_scratchpad.isFormValid = true; // Line executs If there is no answer from GlideAjax
		g_form.submit('submit'); // Form Submission
   }
}

 

Then this Catalog Client Script calls client callable Script Include named "ExistingIncidentFinder" (note: no spaces in the name) and then "findExistingIncident" function within this Script Include:

var ExistingIncidentFinder = Class.create();
ExistingIncidentFinder.prototype = Object.extendsObject(global.AbstractAjaxProcessor, {

findExistingIncident: function() {
	var caseExists = '';
	var firstParameter = this.getParameter('sysparm_field1');
	var secondParameter = this.getParameter('sysparm_field2');
	var thirdParameter = this.getParameter('sysparm_field3');

	var incidentGR= new GlideRecord('table of interest');
	incidentGR.addActiveQuery(); // If you need to search for the active case only
	incidentGR.addQuery('field1', firstParameter);
	incidentGR.addQuery('field2', secondParameter);
	incidentGR.addQuery('field3', thirdParameter);
	incidentGR.query();

	if(incidentGR.next()) { 	// This looks only for one record, use while(caseGR.next()) when multiple records
		incidentExists = incidentGR.getDisplayValue('number');
                incidentItem = incidentGR.getDisplayValue('cmdb_ci');
                incidentSubcategory = incidentGR.getDisplayValue('subcategory')
	}

	if(incidentExists != '') {
		var message = "The existing incident" + incidentExists + " for " + incidentItem + " with the issue related to " + incidentSubcategory + " has been found"; 
	}

	return message;
	
},

    type: 'ExistingCaseFinder'
});

 

This helps to prevent duplicate case creation, for example, when multiple people report outage of the same item, the message will show that the incident has already been created for the same item. 

Pritam Khude
Tera Contributor

Helpful article.

Version history
Last update:
‎09-20-2020 06:04 AM
Updated by: