OnChange client script going in loop

Hafsa1
Mega Sage

I have onChange client script to call 2 fields using script include based on field "Region".

If I select "Region", then location1 and location2 populates correctly and then I save the form.

But if I select "Region", then both location value populate correctly but I didn't save the form, and then select different "Region" again. value of region,location1 and location2 keeps changes/shuffle between selected values. It's going in loop. below is my script

...................................

function onChange(control, oldValue, newValue, isLoading, isTemplate) {
    if (isLoading || newValue === '' || newValue == oldValue) {
        return;
    }
    //Type appropriate comment here, and begin script below

    var Region = g_form.getDisplayValue('u_region');

    var gr = new GlideAjax('RegionHubUtils');
    gr .addParam('sysparm_name', 'getArea1Hub');
    gr .addParam('sysparm_location1', Region);
    gr .getXMLAnswer(function(answer) {
        g_form.setValue('u_location_1', answer);
    });
    var gr1 = new GlideAjax('RegionHubUtils');
    gr1 .addParam('sysparm_name', 'getArea2Hub');
    gr1 .addParam('sysparm_location2', Region);
    gr1 .getXMLAnswer(function(answer1) {
        g_form.setValue('u_location_2', answer1);
    });
...............................................
8 REPLIES 8

Nilesh Pol
Kilo Sage

@Hafsa1 Replace your script include with this code. It also fixes a typo in your original class declaration.

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

getRegionDetails: function() {
var regionID = this.getParameter('sysparm_region');
var result = {
location1: '',
location2: ''
};

// Query for Location 1 (using u_region mapping)
var gr1 = new GlideRecord('sn_customerservice_location_hub');
gr1.addQuery('u_region', regionID);
gr1.query();
if (gr1.next()) {
result.location1 = gr1.getValue('u_location1') || '';
}

// Query for Location 2 (using u_region_new mapping)
var gr2 = new GlideRecord('sn_customerservice_location_hub');
gr2.addQuery('u_region_new', regionID);
gr2.query();
if (gr2.next()) {
result.location2 = gr2.getValue('u_location2') || '';
}

// Return both values as a single JSON string
return JSON.stringify(result);
},

type: 'RegionHubUtils'
});

 

Replace your onChange Client Script with the logic below. This passes the safe newValue variable (the sys_id) to the server instead of the display name.

 

function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if (isLoading || newValue === '') {
// Optional: Clear values if Region is emptied out
if (newValue === '') {
g_form.setValue('u_location_1', '');
g_form.setValue('u_location_2', '');
}
return;
}

var ga = new GlideAjax('RegionHubUtils');
ga.addParam('sysparm_name', 'getRegionDetails');
ga.addParam('sysparm_region', newValue);
ga.getXMLAnswer(function(answer) {
if (answer) {
var data = JSON.parse(answer);
g_form.setValue('u_location_1', data.location1);
g_form.setValue('u_location_2', data.location2);
}
});
}

 

yashkamde
Mega Sage

Hello @Hafsa1 ,

 

try using this optimized script, may be that behaviour is because of asynchronous conditions hitting simultaneously..

Client script :

if (newValue === '') {
        g_form.clearValue('u_location_1');
        g_form.clearValue('u_location_2');
        return;
    }
    if (newValue == oldValue) {
        return;
    }

    var regionVal = newValue; 
    var ga = new GlideAjax('RegionHubUtils');
    ga.addParam('sysparm_name', 'getHubLocations');
    ga.addParam('sysparm_region', regionVal);
    
    ga.getXMLAnswer(function(answer) {
        if (g_form.getValue('u_region') !== newValue) {
            return; 
        }

        if (answer) {
            var locData = JSON.parse(answer);
            g_form.setValue('u_location_1', locData.location1);
            g_form.setValue('u_location_2', locData.location2);
        }
    });


Script Include :

getHubLocations: function() {
        var regionId = this.getParameter('sysparm_region');
        var results = {
            location1: '',
            location2: ''
        };

        var grLoc1 = new GlideRecord('sn_customerservice_location_hub');
        grLoc1.addQuery('u_region', regionId);
        grLoc1.setLimit(1); //We only need one record
        grLoc1.query();
        if (grLoc1.next()) {
            results.location1 = grLoc1.getValue('u_location1') || '';
        }

        var grLoc2 = new GlideRecord('sn_customerservice_location_hub');
        grLoc2.addQuery('u_region_new', regionId);
        grLoc2.setLimit(1);
        grLoc2.query();
        if (grLoc2.next()) {
            results.location2 = grLoc2.getValue('u_location2') || '';
        }

        return JSON.stringify(results);
    },

 

If my response helped mark as helpful and accept the solution.

Ankur Bawiskar
Tera Patron

@Hafsa1 

call Script include only 1 time using GlideAjax and return multiple values from it as JSON object

parse and then set

check this blog

Get User Details based on the Logged in user/ User selected in Client Script 

💡 If my response helped, please mark it as correct and close the thread 🔒— this helps future readers find the solution faster! 🙏

Regards,
Ankur
Certified Technical Architect  ||  10x ServiceNow MVP  ||  ServiceNow Community Leader

vaishali231
Kilo Sage

Hey @Hafsa1 

Your issue is happening because multiple asynchronous GlideAjax calls are returning out of order. 

Use ONE GlideAjax call and return both values together.

Client Script:

function onChange(control, oldValue, newValue, isLoading, isTemplate) {
   if (isLoading || !newValue || newValue == oldValue) {
       return;
   }
   // Clear existing values immediately
   g_form.clearValue('u_location_1');
   g_form.clearValue('u_location_2');
   // Store current selected region
   var selectedRegion = newValue;
   var ga = new GlideAjax('RegionHubUtils');
   ga.addParam('sysparm_name', 'getLocations');
   ga.addParam('sysparm_region', selectedRegion);
   ga.getXMLAnswer(function(response) {
       // Prevent old async response from overwriting latest selection
       if (g_form.getValue('u_region') != selectedRegion) {
           return;
       }
       if (response) {
           var data = JSON.parse(response);
           g_form.setValue('u_location_1', data.location1 || '');
           g_form.setValue('u_location_2', data.location2 || '');
       }
   });
}

Script Include:

var RegionHubUtils = Class.create();
RegionHubUtils.prototype = Object.extendsObject(AbstractAjaxProcessor, {
   getLocations: function() {
       var region = this.getParameter('sysparm_region');
       var result = {
           location1: '',
           location2: ''
       };
       var gr = new GlideRecord('sn_customerservice_location_hub');
       gr.addQuery('u_region', region);
       gr.query();
       if (gr.next()) {
           result.location1 = gr.getValue('u_location1');
           result.location2 = gr.getValue('u_location2');
       }
       return JSON.stringify(result);
   },
   type: 'RegionHubUtils'

});

****************************************************************************

If this response helps, please mark it as Accept as Solution and Helpful.

Doing so helps others in the community and encourages me to keep contributing.

Regards

Vaishali Singh

Servicenow Developer
Linkedin - https://www.linkedin.com/in/vaishali-singh-2273361bb