- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
on 05-17-2020 08:06 PM
Hi,
Recently I came across an issue related to Order Guide Attachments. One of our clients had a requirement that the items present in Service Catalog should have mandatory Attachments, but based on some conditions. The OOB checkbox 'Mandatory Attachment' did not help as the attachment needs to be mandatory if the user selects a particular choice option. As a result we were required to use a custom script that would execute on submit of the catalog form and prevent teh user from submitting if the attachment has not been attached.
I took the help from the following link to deal with the requirement. I created an UI Script which was included in the Service Portal JS Theme and called from the client script. This runs perfectly for the individual items. :
The main problem came when using Order Guides. In individual items, the widget uses the id 'sc_cat_item' for defining the catalog item element. As a result, angular.element("#sc_cat_item").scope() returns the scope of the catalog item and we can access the attachments from this particular scope. But in case of order guides, this element is not present. Since there are multiple items related to the order guide, each item id is defined in a unique id to distinguish between them.
I have made changes to the initial script which has helped me to work with this issue. Apparently, ServiceNow defines each item in an Order Guide display page with the item's sys_id in this format - #itemsysid. I have added a new Ui Script that would execute based on the item id for Order Guide. Here is the UI Script code:
function getSCAttachmentCountOrderGuide(itemSysID) {
var length;
try {
var itemID = '#' + itemSysID;
length = angular.element(itemID).scope().item.attachments.length;
} catch (e) {
length = -1;
}
return length;
}
In the client script, i have added a condition to check if the item is a part of Order Guide or displayed as an individual item. The OOB function g_service_catalog.isOrderGuide() checks if the item is a part of Order Guide or individual item. Here is the code for client script:
try {
var orderGuide = gel('order_item_title').innerHTML;
if(orderGuide != 'This Item')
{
var attachments = document.getElementById('header_attachment_list_label');
if (attachments.style.visibility == 'hidden' || attachments.style.display == 'none') {
alert("Please attach your Manager's approval before submitting the item.");
return false;
}
}
}
//For Service Portal
catch (e) {
var isOrderGuide = g_service_catalog.isOrderGuide();
if (isOrderGuide == true) {
var count = getSCAttachmentCountOrderGuide(g_form.getUniqueValue());
if (count <= 0) {
g_form.addErrorMessage("Please attach your Manager's approval before submitting the item.");
return false;
}
} else {
var count = getSCAttachmentCount();
if (count <= 0) {
g_form.addErrorMessage("Please attach your Manager's approval before submitting the item.");
return false;
}
}
}
The scope of the angular element allows a lot of scope for customizing. We can retrieve a plethora of information from the item scope related to a particular item.
Hope you will find this article helpful. Please let me know your valuable feedback regarding this solution.
If this article has helped you , then please bookmark it or mark it as helpful.
Thanks,
Avisek Dutta
- 3,000 Views
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
THANK YOU SO MUCH FOR THIS!
I was trying everything and googling if anyone else had solutions, as we have an order guide that utilises multiple catalog items but OOTB only enforces one attachment to be created for the order guide.
Perfect solution!
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Thank you for your kind words.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Thanks Avisek, this saved a lot of time! Excellent!!👍
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hello,
dor some reason this isnt working for us. we are on Orlando. The sys ID seems to be passed through tot he UI script, but it is returning error "TypeError: Cannot read property 'length' of undefined". in my case I m checking for multiple attachments, but that should not make a difference.
below is the script:
function getSCAttachmentCountOrderGuide(itemSysID) {
var length;
try {
var itemID = '#' + itemSysID;
length = angular.element('#itemSysID').scope().item.attachments.length;
} catch (e) {
length = e + ' | ' + itemID;
}
return length;
}
and here is the onSubmit:
function onSubmit() {
/*
Confirms the number of attached documents matches the number of variables answered 'yes'.
Calls getSCAttachmentCount function from UI Script CatalogItemFunctions which should be a JS include for our theme
*/
//Collecting and storing the answers in an array. Also declaring the search value we want
var answerArray = ['qa_documents', 'documents_available', 'sla_document', 'risk_assessment_review', 'formal_periodic_access', 'security_assessment_performed', 'patch_management'];
var msgArray = [];
for (var i = 0; i < answerArray.length; i++) {
if (g_form.getValue(answerArray[i]) == 'Yes') {
msgArray.push(answerArray[i]);
}
}
//Comparing the number of attachments on the form to the number of times YES occures in the array variable
var yesCount = msgArray.length;
var msg = getMessage('ITS - QRM number of docs to attach');
var isOrderGuide = g_service_catalog.isOrderGuide();
alert(isOrderGuide);
if (isOrderGuide == true) {
var OgCount = getSCAttachmentCountOrderGuide(g_form.getUniqueValue());
alert('attachment count: ' + this.document.getElementsByClassName('get-attachment').length + ' | yesCount: ' + yesCount + '| OgCount: ' + OgCount);
if (OgCount < yesCount) {
getMessage(msg, function(msg) {
alert(yesCount + ' ' + msg);
});
return false;
}
} else {
alert("2 - cat item condition is running");
var attachmentsCount = getSCAttachmentCount();
if (attachmentsCount < yesCount) {
getMessage(msg, function(msg) {
alert(yesCount + ' ' + msg);
});
return false;
}
}
}
Any guidance would be appreciated !
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Just wanted to correct myself. in our use case, we do still want to the form to progress if the user answers "No" to certain questions. so if this is your requirement, just change the -1 to 0 in the catch section of the script, and it should work as expected.
Thanks Avisek Dutta for sharing this!
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi Mufeed,
Can you please tell me what are the logs you are receiving?

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
We are on Utah. This script is working perfectly for the portal but I'm getting this error in native.
Even with the error, it allows me to submit in native without an attachment. I could sure use some help.
Here is what i did:
Created the UI Script - tried both setting the UI type as portal and as all and get the same error
Created the client script in the catalog item (not the order guide):
Here is the full code:
function onSubmit() {
if(g_form.getValue('request_type') == 'New'){
if (g_form.getValue('pic_attachment') == '') {
try {
var orderGuide = gel('order_item_title').innerHTML;
if (orderGuide != 'This Item') {
var attachments = document.getElementById('header_attachment_list_label');
if (attachments.style.visibility == 'hidden' || attachments.style.display == 'none') {
alert("Please attach your badge ID picture");
return false;
}
}
}
//For Service Portal
catch (e) {
var isOrderGuide = g_service_catalog.isOrderGuide();
if (isOrderGuide == true) {
var count = getSCAttachmentCountOrderGuide(g_form.getUniqueValue());
if (count <= 0) {
alert("Please attach your badge ID picture");
return false;
}
} else {
var count = getSCAttachmentCount();
if (count <= 0) {
g_form.addErrorMessage("Please attach your badge ID picture");
return false;
}
}
}
}}
}
Any idea why it is not recognizing the Order guide in native for the "try" and instead proceeding to the error catch?