How to populate list collector from client script

rahul gupta6
Tera Contributor

Hi,

How can we add managers in list collector variable based on group selected in another list collector variable using onSubmit client script.

Kindly note that multiple groups may have same managers but the list collector variable holding managers should contain unique managers.

1 ACCEPTED SOLUTION

@rahul gupta6 

in single GlideAjax this is possible

This should work for you

please enhance it

Script Include: It should be client callable

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

    getUserGroups: function() {

        var managerArr = [];
        var groups = this.getParameter('sysparm_groups');
        var recGrp = new GlideRecord('sys_user_grmember');
        recGrp.addQuery('group.sys_id', 'IN', groups);
        recGrp.query();
        while (recGrp.next()) {
            managerArr.push(recGrp.manager.toString());
        }
        var arrayUtil = new global.ArrayUtil();
        managerArr = arrayUtil.unique(managerArr);
        return managerArr.toString();
    },

    type: 'getAssignGroups'
});

AnkurBawiskar_0-1764755667979.png

onChange catalog client script on 1st variable

function onChange(control, oldValue, newValue, isLoading) {
    if (isLoading) {
        return;
    }

    // give here the list collector variable name
    g_form.clearValue('2ndVariableName');

    var ga = new GlideAjax('getAssignGroups');
    ga.addParam('sysparm_name', "getUserGroups");
    ga.addParam('sysparm_groups', g_form.getValue('1stVariableName')); // give here 1st variable name
    ga.getXMLAnswer(function(answer) {
        if (answer != '') {
            g_form.setValue('2ndVariableName', answer); // give here user_id variable name
        }
    });

}

💡 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  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

View solution in original post

9 REPLIES 9

@rahul gupta6 

Glad to know.

Ensure you add this in ref qualifier on 1st variable so that the group user selects always have manager

Manager [IS NOT EMPTY]

On every change please send the complete sysids of group present in 1st collector variable

if you select 2nd group then you should send 2 sysIds, if you select 3rd group then you should send 3 group sysIds

var val = g_form.getValue('1stVariableName').toString(); // give here 1st variable name
ga.addParam('sysparm_groups', val);

💡 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  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

Thank you Ankur for your reply.

 

Did some changes in the script include. split the groups and in for loop use the push function.

and then sent the list of managers in client script and used the set value function (changed the client script type to onSubmit. And it is working fine now.

@rahul gupta6 

Thank you for marking my response as helpful.

💡 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  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

Ankur Bawiskar
Tera Patron
Tera Patron

@rahul gupta6 

you should use onChange catalog client script on 1st list collector and set value in 2nd variable

I created blog for something similar, check that and enhance it based on your requirement

it works in both native + portal

Dynamically set list collector on change of variable 

💡 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  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

AbinC
Tera Guru

Hi @rahul gupta6 ,

use an onChange Catalog Client Script on the first List Collector to drive/set the value of the second variable. Here’s a ready-to-use pattern you can adapt, plus a couple of variations depending on what the second variable is (another list collector, a reference, or a multi-select).

Works in both native UI and Service Portal, as long as you stick to g_form APIs and use GlideAjax for server lookups.

If your second variable is another list collector that accepts the same table values, you can directly pass the comma-separated sys_id list.

Variable names (example):

  • lc_src → First list collector (source)
  • lc_target → Second list collector (target)

Client Script (Catalog, type: onChange, variable: lc_src)

 
 
 
 
 
 
JavaScript
 
 
function onChange(control, oldValue, newValue, isLoading) {
if (isLoading) return;
 
// sys_ids comma-separated
var selectedIds = g_form.getValue('lc_src') || '';
// Optional: avoid redundant updates
if (selectedIds === (g_form.getValue('lc_target') || '')) return;
 
// Set the second list collector to the same selection
g_form.setValue('lc_target', selectedIds);
}
 
Show more lines
 

Note: g_form.getValue('<list_collector>') returns sys_ids, while g_form.getDisplayValue('<list_collector>') returns labels (comma-separated). For setting values, use sys_ids.

If the second variable is a reference or a multi-select, or needs mapping (e.g., “Users selected in Group LC → their Managers”), use GlideAjax to fetch/transform server-side, then set the client value.

Example Scenario:

  • lc_src=List collector of Users (sys_user)
  • ref_target = Reference to Department (cmn_department) that should be derived from users’ departments (unique)

1) Script Include (Client-callable)

 
 
 
 
 
 
JavaScript
 
 
var CatalogValueHelper = Class.create();
CatalogValueHelper.prototype = {
initialize: function() {},
 
// Return a comma-separated list of target sys_ids based on source selections
getDepartmentsForUsers: function(userIdsCsv) {
if (!userIdsCsv) return '';
 
var ids = userIdsCsv.split(',');
var unique = {};
var deptList = [];
 
var usr = new GlideRecord('sys_user');
usr.addQuery('sys_id', 'IN', ids);
usr.query();
while (usr.next()) {
var dept = usr.getValue('department');
if (dept && !unique[dept]) {
unique[dept] = true;
deptList.push(dept);
}
}
return deptList.join(',');
},
 
type: 'CatalogValueHelper'
};
 
 
Show more lines
 

Ensure Client Callable is checked if you want direct GlideAjax access from the portal/native.

2) Catalog Client Script (onChange on lc_src)

 
 
 
 
 
 
JavaScript
 
 
function onChange(control, oldValue, newValue, isLoading) {
if (isLoading) return;
 
var selectedUserIds = g_form.getValue('lc_src') || '';
if (!selectedUserIds) {
g_form.clearValue('ref_target');
return;
}
 
var ga = new GlideAjax('CatalogValueHelper');
ga.addParam('sysparm_name', 'getDepartmentsForUsers');
ga.addParam('sysparm_user_ids', selectedUserIds); // custom param name if you alter SI
ga.getXMLAnswer(function(answer) {
// answer is comma-separated sys_ids for target reference/list/multi-select
g_form.setValue('ref_target', answer || '');
});
}
 
Show more lines
 

If you change the Script Include method signature, update the param name retrieval using this.getParameter('sysparm_user_ids').


🧩 Using Display Values (Labels) Instead of sys_ids

If the second variable is a Multi-Select (Select Box) and expects labels, you can do:

 
 
 
 
 
 
JavaScript
 
 
function onChange(control, oldValue, newValue, isLoading) {
if (isLoading) return;
 
var labelsCsv = g_form.getDisplayValue('lc_src') || ''; // labels
// For a multi-select variable that accepts labels
g_form.setValue('multi_select_target', labelsCsv);
}
 
Show more lines
 

This only works if the target variable accepts label text and matches choices.

  • Service Portal vs. Native UI: g_form works in both. Avoid DOM manipulation; stick to APIs.
  • List Collector Values:
    • getValue() → sys_ids (use for setting values).
    • getDisplayValue() → labels (use for showing in read-only/string variables).
  • Ordering: If you need ordering preserved, keep the original sequence of IDs; avoid Set/unique unless required.
  • Performance: For large selections, use a single GlideAjax call that returns all mapped values in one go.
  • Validation: If the target variable has mandatory = true, ensure you set it even when the source changes to empty (clear the target).

if you found this helpful mark it as helpful

 

Thanks,
Abin