Subrahmanyam2
Giga Guru

Note: The functionality explained below uses DOM to achieve desired outcome. From the portal perspective, the approach will only work if the OOB widgets or widgets copied from OOB code are not modified drastically, especially the bits of code which deals with how the attachments added are displayed on browser must not be modified.

STEP1: Create a UI Script which exposes a global function to retrieve count of attachments on platform UI Form
API Name : PlatformUIFormAttachmentUtil
UI Type : Desktop
Global : true [checked]
Active : true
Description : UI Script which exposes a global function to retrieve count of attachments on platform UI Form
Script : As shown below
function getPlatformUIFormAttachmentsCount() {
    try {
        /* Counts the number of attachments added to the form using DOM. Control may not go to catch block even if DOM changes on platform UI */
        return document.querySelectorAll("ul#header_attachment_list li.attachment_list_items>span").length;
    } catch (e) {
        return -1;
    }
}

 

STEP2: Create a UI script which provides utility function to validate the count of attachment(s) on a catalog item request form as well as in order guide (if catalog item is requested through it) in the Service Portal
API Name SPSCItemAttachmentUtil
UI Type : Mobile / Service Portal
Active : true
Description : This UI script provides utility function to validate the count of attachment(s) on a catalog item request form as well as in order guide (if catalog item is requested through it) in the Service Portal
Script : As shown below
function SPSCItemAttachmentUtil() {
    return {
        getSPSCItemAttachmentCount: function (isOrderGuide, g_form) {
            /**
				If the catalog item is used in an order guide pass the sys_id of the catalog item from the sc_cat_item table.
				    Returns -1 if the DOM elements or HTML template of portal widgets change in future
				    Returns 0 if no attachments found in the item.
				    Returns > 0 or count of attachments, if attachments are found
			*/
            var length, id;
            if(isOrderGuide == true) {
                id = g_form.getUniqueValue();
            }
            try {
                if (id == undefined) {
                    try {
                        length = angular.element("#sc_cat_item").scope().attachments.length;
                    } catch (e) {
                        length = 0; // Scope is undefined if there are no attachments, catch block should set length as 0
                    }
                } else {
                    if (angular.element("#" + id).length != 0)
                        length = angular.element("#" + id + " .file-list-wrap ul>li").length;
                    else
                        return -1; // DOM element not found
                }
            } catch (err) {
                return -1; // DOM element not found (or) Found elements property invalid
            }
            return length;
        }
    };
}

 

STEP3: Create an onLoad client script which loads the attachment validation utility function on portal widgets
Name : Load AttachValUIScript
Applies to : A Catalog item
Active : true
UI Type : Mobile / Service Portal
Type : onLoad
Catalog Item : <<Select the desired catalog item on which we need to apply mandatory attachment rules>>
Applies on a Catalog Item view : true
Script : As shown below
function onLoad() {
    if ((typeof g_service_catalog) != 'undefined') { // Makes sure to execute only on Portal
        if (g_service_catalog.u_my_sc_attachmentUtils == undefined) {
            g_ui_scripts.getUIScript('SPSCItemAttachmentUtil').then(function (script) {
                g_service_catalog.u_my_sc_attachmentUtils = script();
            });
        }
    }
}

 

STEP4: Create an onSubmit client script which performs mandatory attachment validations on desired catalog item in portal and platform UI when requested individually or in order guide
Name : Force Attachment AllUIs
Applies to : A Catalog item
Active : true
UI Type : All
Type : onSubmit
Catalog Item : <<Select the desired catalog item on which we need to apply mandatory attachment rules>>
Applies on a Catalog Item view : true
Description: Works on Portal and Platform UI. Single script for both UIs. If you want to throw custom error messge in portal to end user, do not check mandatory attachment checkbox in Catalog item in portal settings tab
Script : As shown below. Please read the comments in the below code to know how to modify it as per your requirement
function onSubmit() {
    var madatoryAttachmentCondition = true; 
    // Pass true if you need atleast one attachment irrespective of varaiable fields filled by user. 
    // Otherwise provide a condition instead of true value : Example - 
    // (g_form.getValue('Variable1Name') == "Variable1Value" && g_form.getValue('Variable2Name') == "Variable2Value");
    var desiredAttachmentCount = 1; 
    // Must be greater than or equal to 1 to work properly. 
    // Provide how many minimum number of attachments  required from user's end to submit the given catalog item.
    var attach_validation_fail_msg = "'<<ItemName>>' request attachment validation failure: <<Custom Error Message Goes Here>>!"; 
    // Replace or pass an error message text as relevant to your business case
    if (madatoryAttachmentCondition) {
        var attachmentCount;
        if ((typeof g_service_catalog) == 'undefined') { // Block executes for Platform View (For both OrderGuide and Direct Request Submission)
            attachmentCount = getPlatformUIFormAttachmentsCount();
            if (attachmentCount == -1) {
                alert("Attachment validation issue! Please contact System Admin!");
                return false;
            }
            if (attachmentCount < desiredAttachmentCount) {
                alert(attach_validation_fail_msg);
                return false;
            } else {
                return true;
            }
        } else { // This block executes in ServicePortal (For both OrderGuide and Direct Request Submission)
            var isOrderGuide = g_service_catalog.isOrderGuide();
            attachmentCount = g_service_catalog.u_my_sc_attachmentUtils.getSPSCItemAttachmentCount(isOrderGuide, ((isOrderGuide == true)?g_form:""));
            if (attachmentCount >= desiredAttachmentCount) {
                return true;
            } else {
                if (attachmentCount == -1)
                    alert("Attachment validation issue! Please contact System Admin!"); //Review SPSCItemAttachmentUtil UI Script function and check to see if there are any DOM changes after upgrade and update script accordingly to solve the issue;
                else
                    alert(attach_validation_fail_msg);
                return false;
            }
        }
    }
}

Once all these changes are done, do remember to check if system is performing mandatory attachment validations as mentioned here:
i) During submission of catalog item request in platform UI
ii) During submission of catalog item request in service portal.
iii) Platform UI: Choose the catalog item in an order guide and test during check out or switching to next tab
iv) Portal UI: Choose the catalog item in an order guide and test during submission

After implementing all the 4 scripts, if you need to use this for more catalog items duplicate STEP3 and STEP4 scripts with desired modifications and choose the catalog item on which you need to perform mandatory attachment validations

Final Notes:
Few part(s) of the code references mentioned above were already mentioned in individual articles in the past. But was unable to find the code which works in all scenarios and UIs uniformly.

Reasons why I chose the approach mentioned in the above steps:

  • Limited DOM traversal only  2 UI scripts, to make it easier to maintain code. Even if there are changes to UI in future, we may just need to update these two UI scripts in future.
  • Both onLoad and onSubmit scripts are required to make it work. Reason for doing this way is:
    • To make sure that UI script loads only when it is required.
  • Desktop UI attachment validation script in STEP1 is kept as global as the dynamic loading did not work during on load in service catalog forms.
Comments
chirag_bagdai
ServiceNow Employee
ServiceNow Employee

Thanks for sharing. I thought of trying other approach in which you don't completely rely on DOM. Please take a look at below article and see if that helps you to simply your code.

https://community.servicenow.com/community?id=community_article&sys_id=9c9cde161bc60190c790ece6b04bc...

 

Francis Cavaciu
Giga Guru

As I mentioned on another post, best practice would be to avoid DOM and Scripting and instead use an Attachment Variable. This should solve all of the issues you are facing with much less risk.

This is also a nicer experience for the end user as you can add instructions and titles to better guide the user.

Create Variable
find_real_file.png

Create Catalog UI Policy
find_real_file.png

Result is a mandatory Attachment Variable
find_real_file.png

Rparida
Tera Contributor

i would also like to show error if no attachment like pls add attachment.is it possible?

 

Version history
Last update:
‎03-05-2022 05:55 PM
Updated by: