Auto-populate List Collector field based on another field selection in Catalog Item
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
a week ago
Hi all
In our Service Catalog item, we have a variable called Select the Application and another variable called Notify Additional User, which is a List Collector.
We have a requirement that
when the user selects Concur in the Select the Application field,
the Notify Additional User field should automatically populate with a specific set of users.
I tried using a Catalog Client Script + Script Include (Client Callable) approach to set values using g_form.setValue() and GlideAjax, but it didnāt work.
The Notify Additional User field is a List Collector type variable, so maybe setValue() doesnāt work directly.
Has anyone implemented a similar scenario
How can I auto-populate the List Collector field with multiple users based on the selected application value
Any help or example script would be appreciated. š
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
a week ago
Hi @aparnaravi,
If you're using the setValue in the client script, try adding the "glide_list" variable attribute in your list collector variable
------------------------------------------------------------------------------------------------------------------------------------
Please mark my response helpful and accept as solution
Thanks & Regards
Mayank
Rising Star 2025
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
a week ago
ServiceNow ā Service Catalog: Auto-populate a List Collector (Notify Additional User) based on 'Select the Application'
Use Case
In a Catalog Item, when the user selects a specific application (e.g., 'Concur') in variable 'Select the Application', you want to auto-populate a List Collector variable 'Notify Additional User' with a predefined set of users. The List Collector should show those users already selected without manual action.
Key Points (List Collector Behavior)
- A Service Catalog List Collector stores its selection as a COMMA-SEPARATED LIST of sys_ids.
- You can set it with: g_form.setValue('<list_collector_name>', 'sysid1,sysid2,sysid3');
- After setting the value, call: g_form.refreshSlushbucket('<list_collector_name>') to refresh the dual-list UI.
- Always use the variable *Name* (not the Label) in client scripts.
Recommended Pattern
1) OnChange Catalog Client Script on 'Select the Application'.
2) Use GlideAjax to fetch the correct user sys_ids for the selected application.
3) In the callback, set the list collector value to a comma-separated string and refresh the slushbucket.
A) Catalog Client Script (onChange on 'Select the Application')
Type: onChange
Applies to: Catalog Items
UI Type: All (or Desktop as needed)
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if (isLoading) return;
// Replace with your variable names
var VAR_APP = 'select_the_application';
var VAR_USERS = 'notify_additional_user';
// Reset when empty or not Concur
if (!newValue) {
g_form.setValue(VAR_USERS, '');
g_form.refreshSlushbucket(VAR_USERS);
return;
}
// If you need to target only Concur by name, compare display value:
// var disp = g_form.getDisplayBox(VAR_APP).value; // display text (if reference or select)
// if (disp !== 'Concur') { ... }
var ga = new GlideAjax('SCNotifyDefaults');
ga.addParam('sysparm_name', 'getDefaultUsersForApp');
ga.addParam('sysparm_app', newValue); // pass selected app value (sys_id or choice value)
ga.getXMLAnswer(function(ans) {
// ans should be 'sysid1,sysid2,sysid3' or '' if none
if (typeof ans === 'string') {
g_form.setValue(VAR_USERS, ans);
g_form.refreshSlushbucket(VAR_USERS);
} else {
g_form.setValue(VAR_USERS, '');
g_form.refreshSlushbucket(VAR_USERS);
}
});
}
Notes:
- If 'Select the Application' is a *reference* to an Application table, newValue is a sys_id. If it's a *select/choice*, it's the choice value. Adjust server query accordingly.
- If you only want this logic for 'Concur', check the display value OR map by the sys_id of Concur for reliability.
B) Script Include (Client Callable) ā Return comma-separated sys_ids
Name: SCNotifyDefaults
Client Callable: true
var SCNotifyDefaults = Class.create();
SCNotifyDefaults.prototype = Object.extendsObject(AbstractAjaxProcessor, {
getDefaultUsersForApp: function() {
var appIdOrValue = (this.getParameter('sysparm_app') || '').toString();
if (!appIdOrValue) return '';
// OPTION 1: Use a mapping table (recommended for maintainability)
// Table: u_app_notify_defaults (u_application REF, u_user REF, active TRUE/FALSE)
var users = [];
var map = new GlideRecord('u_app_notify_defaults');
map.addActiveQuery();
// If 'Select the Application' is a REFERENCE, compare to a reference field
map.addQuery('u_application', appIdOrValue);
// If it's a CHOICE field instead, use name/value lookups here (adjust accordingly)
map.query();
while (map.next()) {
if (map.u_user) users.push(map.u_user.toString());
}
return users.join(',');
// OPTION 2: Hardcode by Application (quick approach)
/*
var out = [];
// 'Concur' sys_id or value; replace 'YOUR_CONCUR_SYS_ID' with actual id/value
if (appIdOrValue === 'YOUR_CONCUR_SYS_ID_OR_VALUE') {
out = ['USER_SYS_ID_1','USER_SYS_ID_2','USER_SYS_ID_3'];
}
return out.join(',');
*/
},
isPublic: function() { return true; }
});
C) Variable Configuration Checklist
- 'Notify Additional User' (List Collector):
⢠List table: sys_user
⢠Reference qualifier: ensure it does NOT exclude your default users. If necessary, adjust ref qual to include them.
⢠Name: notify_additional_user (use this in scripts)
- 'Select the Application':
⢠If it's a reference, newValue in client script is the sys_id.
⢠If it's a choice, newValue is the choice value. You might need to look up the App record or maintain a mapping table keyed by value.
D) Common Pitfalls & Fixes
1) Using setValue with display names -> WRONG. Use sys_ids, comma-separated.
2) Not refreshing slushbucket -> the UI wonāt display selections until g_form.refreshSlushbucket() is called.
3) Using variable Label instead of Name -> scripts fail silently.
4) Ref Qual removes your preselected users -> ensure your qualifier includes them.
5) Client script not running -> make sure 'Applies to' includes the Catalog Item and the UI policy doesnāt make the field read-only until after population.
6) Mobile vs Desktop -> If using Mobile, confirm UI Type includes Mobile or use a different approach.
E) Optional: Lock the defaults for 'Concur'
If you want the selection to be read-only when Concur is chosen:
- After setting the values, call: g_form.setReadOnly('notify_additional_user', true);
- On other apps, set it back to false.
F) Server-Only Alternative (No Client Script)
- Use a 'Run script' step in Flow Designer (on request submitted) or a Before Insert Business Rule on sc_req_item to set RITM variables programmatically:
var ritm = new GlideRecord('sc_req_item'); ...
ritm.variables.notify_additional_user = 'sysid1,sysid2,sysid3';
- This guarantees persistence even if the client script fails, but wonāt show the preselection during form fill.
TL;DR
- Return a comma-separated list of user sys_ids for the selected app via GlideAjax.
- Set the List Collector value with g_form.setValue('<name>', 'id1,id2,id3') and then call g_form.refreshSlushbucket('<name>').
- Maintain the mapping in a small table (u_app_notify_defaults) or hardcode IDs initially.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
a week ago
ServiceNow ā Autoāpopulate a List Collector (Notify Additional User) based on āSelect the Applicationā
Goal
When the requester selects āConcurā in the catalog variable āSelect the Applicationā, autoāpopulate the List Collector variable āNotify Additional Userā with a predefined set of users (multiple sys_ids).
Key points about List Collectors
- They accept a commaāseparated list of sys_ids.
- After setting the value, call: g_form.refreshSlushbucket('variable_name') so the UI updates.
- Use an onChange Catalog Client Script on the driving variable (āSelect the Applicationā).
- Get the target users via GlideAjax (clientācallable Script Include) or a simple mapping table.
- Clear/reset when the selection is not Concur.
A. Catalog Client Script (onChange on āSelect the Applicationā)
Type: onChange | Applies to: Catalog Client Script | UI Type: All
Variable name example:
- Select the Application ā var name: application (reference to some app table or select box)
- Notify Additional User (List Collector) ā var name: notify_additional_user (reference = sys_user)
Script:
function onChange(control, oldValue, newValue, isLoading) {
if (isLoading) return;
// Adjust these to your variable names
var VAR_APP = 'application';
var VAR_LC = 'notify_additional_user';
// If cleared or not Concur, reset list collector and exit
if (!newValue) {
g_form.setValue(VAR_LC, '');
if (g_form.refreshSlushbucket) g_form.refreshSlushbucket(VAR_LC);
return;
}
// Normalize and check for Concur (depending on how your app variable stores value)
// If it's a select box with text values, compare display. If it's a reference, compare sys_id or displayValue.
var isConcur = false;
// Example 1: application is a select box storing text "Concur"
var selectedText = g_form.getDisplayBox(VAR_APP) ? g_form.getDisplayBox(VAR_APP).value : '';
if ((selectedText || '').toLowerCase() === 'concur') isConcur = true;
// Example 2 (uncomment if 'application' is a reference): check display value
// var appDisplay = g_form.getDisplayValue(VAR_APP) || '';
// if (appDisplay.toLowerCase() === 'concur') isConcur = true;
if (!isConcur) {
g_form.setValue(VAR_LC, '');
if (g_form.refreshSlushbucket) g_form.refreshSlushbucket(VAR_LC);
return;
}
// Fetch default users for Concur via GlideAjax
var ga = new GlideAjax('CatalogNotifyDefaults');
ga.addParam('sysparm_name', 'getUsersForApp');
ga.addParam('sysparm_app', 'Concur'); // or pass newValue/sys_id if your mapping uses ids
ga.getXMLAnswer(function(ans) {
// Expect a comma-separated list of sys_ids or empty string
if (ans) {
g_form.setValue(VAR_LC, ans);
if (g_form.refreshSlushbucket) g_form.refreshSlushbucket(VAR_LC);
} else {
g_form.setValue(VAR_LC, '');
if (g_form.refreshSlushbucket) g_form.refreshSlushbucket(VAR_LC);
}
});
}
B. Clientācallable Script Include (returns sys_ids)
Name: CatalogNotifyDefaults | Accessible from: Global or your app scope | Client callable: true
var CatalogNotifyDefaults = Class.create();
CatalogNotifyDefaults.prototype = Object.extendsObject(AbstractAjaxProcessor, {
getUsersForApp: function() {
// Input can be app display or sys_id; adjust logic as needed
var app = (this.getParameter('sysparm_app') || '').toString().toLowerCase();
// Option 1: Hardcoded mapping (quick start)
var MAP = {
'concur': [
'681bf843c0a8016400b98a06818d57c7', // example sys_id
'46d44a40c0a8010e01b93d1e6bba8f4a'
]
};
if (MAP[app]) return MAP[app].join(',');
// Option 2: Dynamic from a small table (recommended for maintainability)
// Table: u_app_notify_defaults (fields: u_app_name, u_user reference: sys_user, u_active)
var ids = [];
var gr = new GlideRecord('u_app_notify_defaults');
gr.addQuery('u_active', true);
gr.addQuery('u_app_name', 'CONTAINS', app); // or '=' if you store exact names
gr.query();
while (gr.next()) {
if (gr.u_user) ids.push(gr.u_user.toString());
}
return ids.join(',');
},
isPublic: function() { return true; }
});
C. Common pitfalls & checks
1) Variable names: Use the **variable name**, not the label (e.g., notify_additional_user).
2) List Collector reference: The slushbucket must reference **sys_user** (or a table compatible with your ids).
3) Refresh UI: Always call **g_form.refreshSlushbucket('notify_additional_user')** after setValue.
4) Reference qualifiers: Ensure the list collectorās ref qual doesnāt exclude your default users.
5) Workspace/EC: If using Employee Center / Workspace, set **UI Type = All** and enable **Compatibility Mode** on the form if needed.
6) Readāonly after populate (optional): Use a Catalog UI Policy to set the list collector readāonly when app = Concur (so defaults arenāt removed).
7) OnLoad default (optional): Duplicate the logic in an **onLoad** script to preāfill Concur if the item opens with that value.
D. Minimal āhardcodedā working demo
- Replace the two example sys_ids with real user sys_ids from your instance.
- Paste the onChange script and Script Include, test the flow:
- Change app to Concur ā List Collector fills with your users
- Change app away from Concur ā List Collector clears
E. Alternative: No GlideAjax (pure client) using a JSON map
If the mapping is small and static, you can keep it clientāside:
var DEFAULTS = {'concur': 'id1,id2,id3'};
if (DEFAULTS[app]) {
g_form.setValue('notify_additional_user', DEFAULTS[app]);
g_form.refreshSlushbucket('notify_additional_user');
}
Summary
- List Collectors can be programmatically set with a commaāseparated list of user sys_ids.
- After setting, call refreshSlushbucket to update the dual list UI.
- Use onChange + GlideAjax to fetch the right ids for the selected application (āConcurā), and clear when not applicable.
