Need help: Update a Read-only variable with approvers data on variables value change in catalog item
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-28-2025 12:33 AM
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!!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-28-2025 03:59 AM
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..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-28-2025 04:03 AM
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 as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-28-2025 05:02 AM
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!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-28-2025 05:07 AM
the code you shared is a tested one?
Ankur
✨ Certified Technical Architect || ✨ 9x ServiceNow MVP || ✨ ServiceNow Community Leader
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-28-2025 04:57 AM
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.