Bi-Directional Synchronization of Reference Fields in ServiceNow (Without Infinite Loop)

venkat ajay
Tera Contributor

Hi Community 👋,

I’d like to share a solution for a common but tricky requirement in ServiceNow:
keeping two reference fields synchronized in both directions without causing infinite recursion.


🔍 Requirement

On a ServiceNow form, there are two reference fields:

  • Oracle Supplier

  • Alternate Supplier

Business Need

  • When the user changes Oracle Supplier, the related Alternate Supplier should auto-populate.

  • When the user changes Alternate Supplier, the related Oracle Supplier should auto-populate.

  • The solution must avoid infinite onChange loops.


🛠 Implementation Overview

The solution uses:

  • Two onChange Client Scripts

  • One Script Include

  • GlideAjax for server-side lookup

  • Window-level flags to prevent recursion

Each client script listens to one field and updates the other.
To avoid infinite looping, we use boolean flags stored on the window object.


📌 Client Script 1

Oracle Supplier → Alternate Supplier

// onChange of oracle_supplier
function onChange(control, oldValue, newValue, isLoading) {
if (isLoading || newValue === oldValue) return;

if (window.skipOracleChange) {
window.skipOracleChange = false;
return;
}

var ga = new GlideAjax('SupplierUtils');
ga.addParam('sysparm_name', 'getAlternateFromSupplier');
ga.addParam('sysparm_supplier', newValue);
ga.getXMLAnswer(function(response) {
var result = JSON.parse(response);
window.skipAlternateChange = true;
g_form.setValue('alternate_supplier', result.alternate_name);
});
}

📌 Client Script 2

Alternate Supplier → Oracle Supplier

// onChange of alternate_supplier
function onChange(control, oldValue, newValue, isLoading) {
if (isLoading || newValue === oldValue) return;

if (window.skipAlternateChange) {
window.skipAlternateChange = false;
return;
}

var ga = new GlideAjax('SupplierUtils');
ga.addParam('sysparm_name', 'getSupplierFromAlternate');
ga.addParam('sysparm_alternate', newValue);
ga.getXMLAnswer(function(response) {
var result = JSON.parse(response);
window.skipOracleChange = true;
g_form.setValue('oracle_supplier', result.legal_supplier);
});
}

📘 Script Include

SupplierUtils

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

getAlternateFromSupplier: function() {
var supplierId = this.getParameter('sysparm_supplier');
var result = {};
var gr = new GlideRecord('sn_fin_supplier');
if (gr.get(supplierId)) {
result.alternate_name = gr.getValue('alternate_name');
}
return new JSON().encode(result);
},

getSupplierFromAlternate: function() {
var altId = this.getParameter('sysparm_alternate');
var result = {};
var gr = new GlideRecord('sn_fin_supplier');
if (gr.get(altId)) {
result.legal_supplier = gr.getValue('oracle_supplier');
}
return new JSON().encode(result);
}
});

🔁 Recursion Handling Explained

Without safeguards, this scenario causes an infinite loop:

  1. Oracle Supplier changes

  2. Alternate Supplier auto-updates

  3. Alternate Supplier onChange fires

  4. Oracle Supplier auto-updates

  5. Loop continues indefinitely

Solution

We use two window-level flags:

  • window.skipOracleChange

  • window.skipAlternateChange

When one field is updated programmatically:

  • A flag is set before updating the other field

  • The receiving onChange detects the flag and exits immediately

  • The flag is reset after one skip

This ensures one-time synchronization without recursion.


Advantages of This Approach

  • ✔ Prevents infinite loops reliably

  • ✔ Clean and easy to understand

  • ✔ Uses standard GlideAjax pattern

  • ✔ Modular and reusable Script Include

  • ✔ Minimal code duplication


🏁 Conclusion

This design ensures data consistency between two reference fields while maintaining system stability.
Using simple window flags is an effective and lightweight way to handle bi-directional synchronization in client scripts.

I hope this helps anyone facing a similar requirement.
Happy to hear suggestions or alternate approaches from the community 😊

Thanks,

Venkat Ajay P

0 REPLIES 0