Amarjeet Pal
Kilo Sage
Options
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
3 weeks ago
M2M table in catalog builder (Wizard)
There’s a helpful article on the ServiceNow Community about this, but here’s a quick summary using the Service Offering example:
- When a Service Offering is selected, the related list Available for Subscribers on the catalog item should be populated.
- This behavior can vary based on requirements like User Criteria.
To achieve this:
-
Create two Catalog Wizard Questions:
- One for selecting the Service Offering.
- One for populating the related list.
-
Mapping Difference:
- The first question should have
map to set = false
. - The second should have
map to set = true
.
- The first question should have
-
Technical Setup:
- The first field must be a List Collector.
- It should be placed on a Variable Set.
- Ensure the OOTB Catalog OnChange client script is active on the Variable Set—this is essential for populating the related list dynamically.
function onChange(control, oldValue, newValue, isLoading) {
var CATALOG_QUESTION_NAME =Service offering variable name;
var CATALOG_PRODUCER_NAME = M2M producer set name ;
var CATALOG_PRODUCER_QUESTION_NAME = 'service_offering';
if (isLoading) {
g_form.setDisplay(CATALOG_PRODUCER_NAME, false);
convertRowValuesToCommaSeparatedString(CATALOG_QUESTION_NAME, CATALOG_PRODUCER_NAME, CATALOG_PRODUCER_QUESTION_NAME);
return;
}
var valueArr = !newValue ? [] : newValue.split(',');
addRows(CATALOG_PRODUCER_NAME, CATALOG_PRODUCER_QUESTION_NAME, valueArr);
}
//TODO: move to UI scripts and use it in here.
function addRows(producerSetName, producerSetQuestionName, includedValues) {
var recordMap = getRecordMap(producerSetName, producerSetQuestionName);
var ans = [];
for (var i = 0; i < includedValues.length; i++) {
var row = {};
row[producerSetQuestionName] = includedValues[i];
if (recordMap && recordMap[includedValues[i]])
row['sys_id'] = recordMap[includedValues[i]];
ans.push(row);
}
g_form.setValue(producerSetName, JSON.stringify(ans));
}
function convertRowValuesToCommaSeparatedString(questionName, producerSetName, producerQuestionName) {
var value = g_form.getValue(producerSetName);
try {
value = JSON.parse(value);
} catch (e) {
value = [];
}
var ans = [];
for (var i = 0; i < value.length; i++) {
var row = value[i];
if (row && row.hasOwnProperty(producerQuestionName))
ans.push(row[producerQuestionName]);
}
g_form.setValue(questionName, ans.join());
}
function getRecordMap(producerSetName, producerQuestionName) {
var fieldObj = g_form.$private.getField(producerSetName);
if (fieldObj._recordMap)
return fieldObj._recordMap;
var originalValue = fieldObj.originalValue || '[]';
var originalJSON;
try {
originalJSON = JSON.parse(originalValue);
} catch (e) {
originalJSON = [];
}
var recordMap = {};
for (var i = 0; i < originalJSON.length; i++) {
var obj = originalJSON[i];
if (obj && obj[producerQuestionName] && obj['sys_id'])
recordMap[obj[producerQuestionName]] = obj['sys_id'];
}
fieldObj._recordMap = recordMap;
return fieldObj._recordMap;
}
This is a major step that isn’t documented. Everything else follows the out-of-the-box behavior—try to replicate it similar to how "Available for" (User Criteria ) works.
Thanks
Amarjeet Pal
- 390 Views
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.