Need help: Update a Read-only variable with approvers data on variables value change in catalog item

MHimabindu
Tera Contributor

Hello Community,

 

I am working on catalog item and need some help with a development requirement.

 

Use case: I have around 32 variables in my catalog item. Each of these variable is user-selectable(list collector). Based on variable value empty/filled, I want to dynamically update a read-only variable depending on the non-empty variables. This update needs to happen in real-time on the client side before form submission.

 

I have tried the classic approach with  onChange catalog client scripts on each variable, but this might cause performance issue and is inefficient.

 

I am looking for a better and single script to listen for changes on any variable and updates the read-only variable accordingly.

 

Any help or suggestions are greatly appreciated!!

 

Thanks in advance!!

9 REPLIES 9

Hi @Rafael Batistot 

 

Thanks for response,PFB modified script but not able to get expected output(no alerts as well). I am not sure if I am missing something here..

 

function onLoad() {
var variableNames = ['var1, 'var2', 'var3', '........,'var32'];
 
var amt = g_form.getValue('varA');
var ct = g_form.getValue('varB');
var fml = g_form.getValue('varC');
 
var finalAppMat = [];
 
function updateSummary() {
       var app = [];
 
       variableNames.forEach(function(name) {
            var val = g_form.getValue(name);
            if (val) {
               app.push(name);
            }
         });
         
      if (app.indexOf('var1') != -1)
                    app.push("Optional App");
 
      if (fml == 'test') {
          if ((ct == 'grp') || (cat == 'gp')) {
              if (app.indexOf('var2') != -1)
                   app.push("Global App");
              if (app.indexOf('var3') != -1)
                   app.push("Additional Global App");
                    }
                  }
                           
      var Matrix = "Order of matrix :\n\n";

        if (finalAppMat.length != 0) {
            for (i = 0; i < app.length; i++) {
                Matrix = Matrix + "App" + (i + 1) + " : " +finalAppMat[i] + "\n";
            }
        }
          g_form.setValue('Read-Only Varibale', Matrix);
    }

    // Attach a single event listener to each variable dynamically
    variableNames.forEach(function(name) {
        g_form.attachChangeHandler(name, function() {
            updateSummary();
        });
    });

    // Initial update on load
    updateSummary();
}
 
 
 
Thanks!
 
 

Can you try with below script:

function onLoad() {
var variableNames = ['var1', 'var2', 'var3', /* ..., */ 'var32'];

function updateSummary() {
var amt = g_form.getValue('varA');
var ct = g_form.getValue('varB');
var fml = g_form.getValue('varC');

var app = [];

// Collect all checked or filled-in variables
variableNames.forEach(function(name) {
var val = g_form.getValue(name);
if (val) {
app.push(name);
}
});

// Add extra labels if certain conditions are met
if (app.indexOf('var1') !== -1)
app.push("Optional App");

if (fml === 'test' && (ct === 'grp' || ct === 'gp')) {
if (app.indexOf('var2') !== -1)
app.push("Global App");
if (app.indexOf('var3') !== -1)
app.push("Additional Global App");
}

// Build the matrix string
var matrix = "Order of matrix:\n\n";
for (var i = 0; i < app.length; i++) {
matrix += "App " + (i + 1) + " : " + app[i] + "\n";
}

// Set the read-only variable
g_form.setValue('read_only_variable', matrix); // Make sure variable name is lowercase and correct
}

// Run updateSummary on load
updateSummary();

// Run updateSummary whenever any of the 32 variables change
variableNames.forEach(function(name) {
g_form.setOnChange(name, function() {
updateSummary();
});
});

// Also listen to controlling variables (if they change)
['varA', 'varB', 'varC'].forEach(function(name) {
g_form.setOnChange(name, function() {
updateSummary();
});
});
}

 

Mark it helpful if this helps you to understand. Accept solution if this give you the answer you're looking for
Kind Regards,
Pavani P

Hi @pavani_paluri 

 

Updated accordingly, no change on the read-only field..

 

I have added alerts to check for any breaks in the script but no use.

 

Thanks!

@pavani_paluri 

the code you shared is a tested one?

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

Hi, @MHimabindu 

 

i did some changes, let me know if work now 

 

var variableNames = ['var1', 'var2', 'var3', ..., 'var32']; // Replace with actual variable names
var readOnlyVariableName = 'read_only_variable'; // Replace with your read-only variable name

function updateSummary() {
var selectedApps = [];
var summaryText = "Order of matrix:\n\n";

// Get values from other control variables
var amt = g_form.getValue('varA');
var ct = g_form.getValue('varB');
var fml = g_form.getValue('varC');

// Check which variables are filled
variableNames.forEach(function(name) {
var val = g_form.getValue(name);
if (val) {
selectedApps.push(name); // or g_form.getDisplayValue(name) if you want labels
}
});

// Add custom logic based on selections
if (selectedApps.indexOf('var1') !== -1) {
selectedApps.push("Optional App");
}

if (fml === 'test') {
if (ct === 'grp' || ct === 'gp') {
if (selectedApps.indexOf('var2') !== -1) selectedApps.push("Global App");
if (selectedApps.indexOf('var3') !== -1) selectedApps.push("Additional Global App");
}
}

// Build the matrix text
for (var i = 0; i < selectedApps.length; i++) {
summaryText += "App" + (i + 1) + ": " + selectedApps[i] + "\n";
}

// Set the read-only variable
g_form.setValue(readOnlyVariableName, summaryText);
}

// Attach onChange listeners dynamically
variableNames.forEach(function(name) {
g_form.onChange(name, updateSummary);
});

// Initial run on form load
updateSummary();

 

 

***Use g_form.getDisplayValue(name) if you want to display labels instead of internal values.

 

Ensure “read_only_variable” exists and is set to read-only.

Add this as a Catalog Client Script, type onLoad, and set “Applies to” = “Catalog Item”.


If you’re using List Collector variables, this still works, but for multi-selects, you may want to split values and loop through them.