How To - Select all records for a list collector
A question that popped up on the SNDevs Slack community was a method to have a select all ability for a list collector within a catalog item.
This can be done via a simple script include and a catalog client script that performs a GlideAjax call.
Script Include
This takes the catalog item sys_id as well as the list field in question. It'll evaluate the reference qualifier as part of the select all process and return the records in a JSON structured object.
var MyCatalogUtils = Class.create();
MyCatalogUtils.prototype = Object.extendsObject(global.AbstractAjaxProcessor, {
getRecords: function() {
//As the field name isn't necessairly unique
//pass in the cat item the variable is on
//Note: This won't work for variable sets - modify to your needs!
var fieldName = this.getParameter('sysparm_field_name');
var catItem = this.getParameter('sysparm_cat_item');
//Look up the variable so we can get the list collector info
var variableGR = new GlideRecord('item_option_new');
variableGR.addQuery('name', fieldName);
variableGR.addQuery('cat_item', catItem);
variableGR.setLimit(1);
variableGR.query();
if (variableGR.next()) {
//Create a new GlideRecord query to the table the variable references
var tableLookupGR = new GlideRecord(variableGR.getValue('list_table'));
var encodedQuery = variableGR.getValue('reference_qual');
tableLookupGR.addEncodedQuery(encodedQuery);
var returnValues = [];
tableLookupGR.query();
while (tableLookupGR.next()) {
//Push the value and display value to avoid any synchronous display value calls
//when we populate the list collector on the catalog item
returnValues.push({
"value": tableLookupGR.getUniqueValue(),
"displayValue": tableLookupGR.getDisplayValue()
});
}
return JSON.stringify(returnValues);
}
},
type: 'MyCatalogUtils'
});
We're returning both the value and display value of each record. This avoids ServiceNow performing a synchronous call when we populate the list collector on the catalog item. If we didn't do this, the platform would create a synchronous call for each record populate leading to a poor user experience as the browser window would freeze/hang whilst the synchronous calls complete.
Catalog Client Script
The client script is relatively compact, and only requires one modification which is the list collector field name we're doing the lookup for. For this to run, we're using an onChange catalog client script on a checkbox.
function onChange(control, oldValue, newValue, isLoading) {
if (isLoading) {
return;
}
var listCollectorName = "FIELD_NAME_HERE";
if(g_list != "undefined"){
var listCollector = g_list.get(listCollectorName);
if(!listCollector)return;
}
if(newValue == 'false'){
g_form.setValue(listCollectorName , '');
return;
}
var ga = new GlideAjax('MyCatalogUtils');
ga.addParam('sysparm_name' , 'getRecords');
ga.addParam('sysparm_field_name' , listCollectorName);
ga.addParam('sysparm_cat_item' , g_form.getUniqueValue());
ga.getXMLAnswer(function(response){
if(response == null)return;
response = JSON.parse(response);
if(listCollector){
response.forEach(function(el){
listCollector.addItem(el.value , el.displayValue);
});
} else {
var values = response.map(function(val){ return val.value;});
var display = response.map(function(val){return val.displayValue;});
g_form.setValue(listCollectorName , values.join(",") , display.join(", "));
}
});
}
A special thanks to @Chris Helming for tweaking the code. And Jens for asking the question that got me curious about a solution.
https://www.servicenow.com/community/now-platform-articles/how-to-select-all-records-for-a-list-collector/ta-p/2312497