- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-29-2024 01:37 PM
In ServiceNow, I have a catalog item with two variables.
1. The first variable is called **select_application** and it's a lookup select box. It pulls data from the "cmdb_rel_group" table, specifically from the "ci" field, which is a reference to the "cmdb_ci" table.
2. The second variable is called **select_group_to_be_added_removed** and it's a list collector. It also uses the "cmdb_rel_group" table.
I want to set it up so that when a user selects a specific "ci" in the **select_application** variable, only the groups associated with that specific "ci" are shown in the **select_group_to_be_added_removed** variable.
The group names to be displayed in the **select_group_to_be_added_removed** variable are stored in the "group" field of the "cmdb_rel_group" table, which is a reference to the "sys_user_group" table.
For now I have this catalog client script:
function onChange(control, oldValue, newValue, isLoading) {
if (isLoading || newValue === '') {
return;
}
// Get the sys_id of the selected application (CI)
var selectedApplication = g_form.getValue('select_application');
// Call the script include to get the group options
var ga = new GlideAjax('FilterGroupsByApplication');
ga.addParam('sys_id', selectedApplication);
ga.getXMLAnswer(function(response) {
var groupOptions = response.responseXML.documentElement.getAttribute('answer');
var groupOptionsArr = groupOptions.split(',');
// Clear existing options
var selectElement = g_form.getControl('select_group_to_be_added_removed');
for (var i = selectElement.options.length - 1; i >= 0; i--) {
selectElement.remove(i);
}
// Add the filtered options
for (var j = 0; j < groupOptionsArr.length; j++) {
var option = groupOptionsArr[j];
if (option) {
selectElement.add(new Option(option.split(' - ')[1], option.split(' - ')[0]));
}
}
});
}
and this script include:
var FilterGroupsByApplication = Class.create();
FilterGroupsByApplication.prototype = Object.extendsObject(AbstractAjaxProcessor, {
getGroupOptions: function() {
var applicationSysId = this.getParameter('sys_id');
var groups = [];
var gr = new GlideRecord('cmdb_rel_group');
gr.addQuery('ci', applicationSysId);
gr.query();
while (gr.next()) {
var groupSysId = gr.getValue('group');
var groupName = gr.group.getDisplayValue();
if (groupSysId) {
groups.push(groupSysId + ' - ' + groupName);
}
}
return groups.join(',');
},
type: 'FilterGroupsByApplication'
});
But it doesn't work - anybody can tell me why?
Best regards
Anders
If my answer has helped with your question, please mark my answer as the accepted solution and give a thumbs up.
Best regards
Anders
Rising star 2024
MVP 2025
linkedIn: https://www.linkedin.com/in/andersskovbjerg/
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-30-2024 02:01 AM - edited ‎08-30-2024 02:08 AM
Ah I understand. You have a List Collector here... I was under the assumption you have a Choice-type field.
In this case however, I'd suggest you to completely skip the client side stuff and go with the following:
- On the field "Select Group to be added...":
- "Type specification" -> Set the field "Variable attributes" to "ref_qual_elements=select_application"
- "Type specification" -> Set the field "Reference qualifier" to "javascript: new global.CUSTOMER_MyCatItem().groupRefQual(current);"
With the step 1 you basically make the reference qualifier reload every time you change the 'select_application' value.
- Create a new Script Include (or modify the existing to match):
- Name: CUSTOMER_MyCatItem (naming convention for maintenance, please modify according to your circumstances)
- Client: false (no longer requires ACL!)
- Script:
/* global Class, GlideRecord */
/* eslint no-undef: "error" */
var CUSTOMER_MyCatItem = Class.create();
CUSTOMER_MyCatItem.prototype = {
initialize: function() {
},
/**
* {sc_cart_item & GlideRecordGenerated} itemGr
* @returns {Array.<string>} List of Group SysIDs
*/
groupRefQual: function (cartItemGr) {
var cmdbRelGroupGr = new GlideRecord('cmdb_rel_group');
if (cartItemGr.variables.select_application) {
cmdbRelGroupGr.addQuery('ci', cartItemGr.variables.select_application);
} else {
cmdbRelGroupGr.addQuery('sys_id', 'x');
}
cmdbRelGroupGr.setLimit(50); // best practice to limit all queries, replace with a resonable value
cmdbRelGroupGr.query();
var groupSysIDs = [];
while (cmdbRelGroupGr.next()) {
groupSysIDs.push(cmdbRelGroupGr.getValue('group'));
}
return 'sys_idIN' + groupSysIDs;
},
type: 'CUSTOMER_MyCatItem'
};
The advantage of this solution is: It only requires one (!) additional artefact (the Script Include), while previously you'd additionaly have to have:
- One Client Script
- One ACL protecting the Client Callable Script Include
- The ACL needs to have one acl-role record at least
=> In total you have 4 artefacts to implement (and maintain!) this requirement, while compared with the one presented in this post, you have 1.
In theory you could even inline the whole ref-qual script, but I wouldn't recommend this as maintenance is a lot harder.
If you still want to though (in this case you wouldn't need any additional artefacts on top of your catalog item at all), this is the reference qualifier you have to use (Step 1.1):
javascript: (function (cartItemGr) {
var cmdbRelGroupGr = new GlideRecord('cmdb_rel_group');
if (cartItemGr.variables.select_application) {
cmdbRelGroupGr.addQuery('ci', cartItemGr.variables.select_application);
} else {
cmdbRelGroupGr.addQuery('sys_id', 'x');
}
cmdbRelGroupGr.setLimit(50); // best practice to limit all queries, replace with a resonable value
cmdbRelGroupGr.query();
var groupSysIDs = [];
while (cmdbRelGroupGr.next()) {
groupSysIDs.push(cmdbRelGroupGr.getValue('group'));
}
return 'sys_idIN' + groupSysIDs;
})(current);
Please let us know if this solves your issue, in case please mark the answer which helped you the most as the "solution" to this thread so other community members facing the same issue profit from it.
Edit: Thought some screenshots might help:
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-29-2024 10:53 PM
Hi @Markus Kraus ,
Thank you for the very detailed explanation and scripts :).
I can see through the debugger, that the group is parsed successfully from the script include:
{"status":"success","message":"","groups":[{"value":"d6bb6c131b1d15d4ff17dac8b04bcbc8","name":"Test case"}]}
Though the list collector is still not limited to only show the single group, but still show both groups:
Basically, I would like that only "test case" is available to above scenario.
Best regards
Anders
If my answer has helped with your question, please mark my answer as the accepted solution and give a thumbs up.
Best regards
Anders
Rising star 2024
MVP 2025
linkedIn: https://www.linkedin.com/in/andersskovbjerg/
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-30-2024 02:01 AM - edited ‎08-30-2024 02:08 AM
Ah I understand. You have a List Collector here... I was under the assumption you have a Choice-type field.
In this case however, I'd suggest you to completely skip the client side stuff and go with the following:
- On the field "Select Group to be added...":
- "Type specification" -> Set the field "Variable attributes" to "ref_qual_elements=select_application"
- "Type specification" -> Set the field "Reference qualifier" to "javascript: new global.CUSTOMER_MyCatItem().groupRefQual(current);"
With the step 1 you basically make the reference qualifier reload every time you change the 'select_application' value.
- Create a new Script Include (or modify the existing to match):
- Name: CUSTOMER_MyCatItem (naming convention for maintenance, please modify according to your circumstances)
- Client: false (no longer requires ACL!)
- Script:
/* global Class, GlideRecord */
/* eslint no-undef: "error" */
var CUSTOMER_MyCatItem = Class.create();
CUSTOMER_MyCatItem.prototype = {
initialize: function() {
},
/**
* {sc_cart_item & GlideRecordGenerated} itemGr
* @returns {Array.<string>} List of Group SysIDs
*/
groupRefQual: function (cartItemGr) {
var cmdbRelGroupGr = new GlideRecord('cmdb_rel_group');
if (cartItemGr.variables.select_application) {
cmdbRelGroupGr.addQuery('ci', cartItemGr.variables.select_application);
} else {
cmdbRelGroupGr.addQuery('sys_id', 'x');
}
cmdbRelGroupGr.setLimit(50); // best practice to limit all queries, replace with a resonable value
cmdbRelGroupGr.query();
var groupSysIDs = [];
while (cmdbRelGroupGr.next()) {
groupSysIDs.push(cmdbRelGroupGr.getValue('group'));
}
return 'sys_idIN' + groupSysIDs;
},
type: 'CUSTOMER_MyCatItem'
};
The advantage of this solution is: It only requires one (!) additional artefact (the Script Include), while previously you'd additionaly have to have:
- One Client Script
- One ACL protecting the Client Callable Script Include
- The ACL needs to have one acl-role record at least
=> In total you have 4 artefacts to implement (and maintain!) this requirement, while compared with the one presented in this post, you have 1.
In theory you could even inline the whole ref-qual script, but I wouldn't recommend this as maintenance is a lot harder.
If you still want to though (in this case you wouldn't need any additional artefacts on top of your catalog item at all), this is the reference qualifier you have to use (Step 1.1):
javascript: (function (cartItemGr) {
var cmdbRelGroupGr = new GlideRecord('cmdb_rel_group');
if (cartItemGr.variables.select_application) {
cmdbRelGroupGr.addQuery('ci', cartItemGr.variables.select_application);
} else {
cmdbRelGroupGr.addQuery('sys_id', 'x');
}
cmdbRelGroupGr.setLimit(50); // best practice to limit all queries, replace with a resonable value
cmdbRelGroupGr.query();
var groupSysIDs = [];
while (cmdbRelGroupGr.next()) {
groupSysIDs.push(cmdbRelGroupGr.getValue('group'));
}
return 'sys_idIN' + groupSysIDs;
})(current);
Please let us know if this solves your issue, in case please mark the answer which helped you the most as the "solution" to this thread so other community members facing the same issue profit from it.
Edit: Thought some screenshots might help:
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-30-2024 02:27 AM - edited ‎08-30-2024 02:27 AM
Hi @Markus Kraus ,
Beautiful - Thank you so much for you big help and effort - works like a charm.
/Anders
If my answer has helped with your question, please mark my answer as the accepted solution and give a thumbs up.
Best regards
Anders
Rising star 2024
MVP 2025
linkedIn: https://www.linkedin.com/in/andersskovbjerg/