The Now Platform® Washington DC release is live. Watch now!
on 08-24-2019 01:27 PM
Problem Statement: Need to check if attachment is added or not when user submit a request through service catalog.
I know, there are lots of post regarding making attachments mandatory on Native UI and Service Portal. But very few of them are on working state.
I am tried to summarized all possible ways for making attachment mandatory on different UI types, ServiceNow Versions.
So, Let’s get started…….
Option 1: ServiceNow Madrid Release Feature: Mandatory Attachment with No scripting
If you are using ServiceNow Madrid or later release, then with the help of checkbox available on catalog item you can make attachment mandatory. Also, you can hide a paperclip i.e. attachment icon. Follow the steps as below:
You can go to Portal/Native UI and check if attachment is made mandatory/hidden.
Option 2: Using UI Script, JS Theme, and Client script
Here is other ways that you may have a look as well.
1. ADD A UI SCRIPT
In the Left Navigator Bar, go to System UI > UI Scripts. Click New
UI Script: GlobalCatalogItemFunctions
Global: true
Script:
function getSCAttachmentCount() {
var length;
try {
length = angular.element("#sc_cat_item").scope().attachments.length;
} catch(e) {
length = -1;
}
return length;
}
2. ADD A JS THEME:
3. CREATE A CATALOG CLIENT SCRIPT: For your catalog item you want to require attachments, use this client script.
function onSubmit() {
//Works in non-portal ui
try {
var attachments = document.getElementById('header_attachment_list_label');
if (attachments.style.visibility == 'hidden' || attachments.style.display == 'none' ) {
alert('You must attach the completed form before submitting this request.');
return false;
}
}
//For Service Portal
catch(e) {
var count = getSCAttachmentCount();
if(count <= 0) {
alert('You must attach the completed form before submitting this request.');
return false;
}
}
}
Option 3: Using DOM Manipulation in Client script:
Well with the introduction of London came a new field called 'isolate script'. New client-scripts are run in strict mode, with direct DOM access disabled. Access to jQuery, prototype and the window object are likewise disabled. To disable this on a per-script basis, configure this form and add the "Isolate script" field. To disable this feature for all new globally-scoped client-side scripts set the system property "glide.script.block.client.globals" to false.
Before running this script, Make an Isolate script: False on client script / catalog client script.
1. This script will run UI Types: Native and Service Portal
function onSubmit() {
if(this.document.getElementsByClassName('get-attachment').length == 0) {
alert(''You must add an attachment before submitting this request.');
return false;
}
}
2.This script will run UI Types: Native UI
function onSubmit() {
var attachments = document.getElementById('header_attachment_list_label');
if (attachments.style.visibility == 'hidden' || attachments.style.display == 'none' ) {
alert('You must add an attachment before submitting this request.');
return false;
}
}
Option 4: OnSubmit Client Script with the help of GlideRecord:
GlideRecord and g_form.getReference() are also available for retrieving server information. However, these methods are no longer recommended due to their performance impact in client script. Both methods retrieve all fields in the requested GlideRecord when most cases only require one field.
This script will run on both Native and portal UI as well.
function onSubmit() {
var cat_id = g_form.getValue('sysparm_item_guid');
var gr = new GlideRecord("sys_attachment");
gr.addQuery("table_name", "sc_cart_item");
gr.addQuery("table_sys_id", cat_id);
gr.query();
if (!gr.next()) {
alert("You must add an attachment before submitting this request.");
return false;
}
}
Option 5: OnSubmit Client Script with the help of GlideAjax:
If you are not in Madrid release, then above option is not available for you. In that case, with the help of client
script, you can achieve the above functionality for making attachment mandatory.
Before running this script, Make an ISOLATED SCRIPT: FALSE on client script / catalog client script.
Below script will run on Native UI (Non portal UI).
Client script Code:
function onSubmit() {
// var formID = gel('sysparm_item_guid').value;
// var formID= document.getElementById('sysparm_item_guid').value;
var formID = g_form.getValue('sysparm_item_guid');
// alert("Form ID: "+formID);
var ab = new GlideAjax('global.hasAttachment');
ab.addParam('sysparm_name', 'attachment');
ab.addParam('sysparm_form_id', formID);
ab.getXMLWait();
var isTrue = ab.getAnswer();
if(isTrue == 'yes'){
alert("Kudos to you!! You have added attachment");
return true;
} else if(isTrue == 'no'){
alert("You must attach document before submitting the form.");
return false;
}
Script include Code:
Name: hasAttachment
Client callable: TRUE
Script:
var hasAttachment = Class.create();
hasAttachment.prototype = Object.extendsObject(AbstractAjaxProcessor, {
attachment: function(){
var formID = this.getParameter('sysparm_form_id');
//gs.log("AG formID"+ formID);
var gr = new GlideRecord("sys_attachment");
gr.addQuery('table_name', "sc_cart_item");
gr.addQuery('table_sys_id', dataCheck);
gr.query();
if (gr.next()) {
//gs.log("Kudos to you!! You have added attachment ");
return 'yes';
}else{
//gs.log("You must attach document before submitting the form.");
return 'no';
}
},
type: 'hasAttachment'
});
Advantage:
The server processes the request synchronously and will not process further requests from the client until finished.Using getXMLWait() ensures the order of execution. So this script will give you a correct output on Native UI.
Drawback:
As getXMLWait() is not available to scoped applications and Service Portal does not support synchronous GlideAjax. So, this script will run on portal, but you will not get correct result.
Apart from all the above, you can create a custom Solution by creating a custom widget and make use of it. You can keep this attachment widget at any position on the catalog form. Please check out the below link:
Require Attachments
Hope you will find this article helpful. Please let me know if any other way to achieve this, any suggestions on this.
UPDATE:
There are other ways and options that were available and you can find that in the below link.
Making Attachments Mandatory in SP: The Ultimate Guide (Including Paris)
Thanks to
If this article helped you , then please bookmark it or mark it as helpful.
Thanks,
Abhishek Gardade
Nice post! Thanks for putting it together.
If you happened to get any of that script from the many posts across the Community, please add it's link to the appropriate Option as a way to give credit.
Thanks mark, I will add a links soon
Good One Mate.
Hi, names not Mark, but thanks! Sounds good.
Thanks Ashutosh.
Thanks Hit
Hi Abhishek Gardade,
I have used same script but i am getting length value as -1 when i am trying to submit with order guide in portal even i have attached document.Is any one having idea please respond.
ADD A UI SCRIPT
UI Script: GlobalCatalogItemFunctions
Global: true
Script:
function getSCAttachmentCount() {
var length;
try {
length = angular.element("#sc_cat_item").scope().attachments.length;
} //not reflecting value
catch(e) {
length = -1;
} //repeatedly occuring
return length;
}
Thanks,
Suresh Ch.
hello Suresh,
Where you are writing a script?
Thanks,
Abhishek
Hi! I'm getting an "onSubmit script error: TypeError: Cannot read property 'getElementById' of null: function () { [native code] }" while using Option 3. I've already set the Isolate script to false.
Okay, I've fixed it. I'm working on a scoped app so I created a new system property as stated on this thread:
Great,Why you are not trying Option 1?
Thanks
It's only working on the portal view. I don't know if that's the expected behavior.
Good one!!! Cheers.
Nice post! Thanks a lot
One more Use-case to make attachment mandatory,
Only based on conditions on record-producer or fulfiller (Which is similar to Option 4 type):
function onSubmit() {
//Get the field
var field= g_form.getValue("hr_process");
//Make attachment mandatory only based on conditions.
if(field == 'it_infra'){
var cat_id = g_form.getValue('sysparm_item_guid');
var gr = new GlideRecord("sys_attachment");
gr.addQuery("table_name", "sn_hr_core_case"); //Update your table
gr.addQuery("table_sys_id", cat_id);
gr.query();
if (!gr.next()) {
g_form.addErrorMessage('You must add an attachment before submitting this request.');
return false;
}
}
}
Hello Nen,Abhishek,
I'm facing a similar issue here, is there any oob ans for this?
Quiet Helpful! Please rectify the highlighted portions. It should be either 'formID' or 'dataCheck' at both places.
Hi Mr. World Wide,
i tryed your code but even if i attached a item i run into the Error.
I checked the "sysparm_item_guid" and this seems empty. Is there another Value for Recordproducers in Paris?
Thanks a lot!
Best,
Stephan
These are awesome but has anyone been able to get any of them to work in an Order Guide?? I'm needing something to make attachments mandatory once a question under Describe Needs has an answer of "yes."
I've tried Option 2 but it did not work.
Thanks,
Brandon
One of the simple way for mandatory attachment :
step 1: create one global UI script :
function getSCAttachmentCount() {
var length;
try {
length = angular.element("#sc_cat_item").scope().attachments.length;
} catch(e) {
length = -1;
}
return length;
}
Step 2: Client script:
function onSubmit() {
var field= g_form.getValue('request_version');
if(field== 'New Request')
{
var count = getSCAttachmentCount();
if(count <= 0)
{
alert('Provide a attachment document for this RITM.');
return false;
}
}
Write the script in UI script then add JS Includes in Theme as stated and then call it from Catalog Client script.
You are getting this error even after adding attachment because, your angularjs script is running before DOM could get fully loaded. hence just add script in UI script and then use it from catalog client script.
One even better way - actually making attachments mandatory in real-time
(function() {
"use strict";
return {
setAttachmentMandatory: function(isMandatory) {
var isSuccess;
try {
angular.element("#sc_cat_item").scope().c.data.sc_cat_item.mandatory_attachment = isMandatory;
isSuccess = true;
} catch (e) {
isSuccess = false;
console.log('setAttachmentMandatory() failed: ' + e);
}
return isSuccess;
},
type: "AttachmentUtil"
};
})();
function onChange(newValue, oldValue) {
// add your conditional logic
g_ui_scripts.getUIScript('setAttachmentMandatory').then(function(script) {
script.setAttachmentMandatory(true);
});
}
Hi Suresh,
Did you find any solution for this?
I am facing the same issue in order guide. UI script and theme are correctly placed. It was working fime for catalog items but not in order guide.
Any help will be highly appreciated.
Thanks,
What version are you on?
This solution is someone dated. You can now use Attachment Variables (see Making Attachments Mandatory in SP: The Ultimate Guide (Including Paris) )
Hi Brandon,
I came across a similar situation and is able to figure out a solution.
Please check the below article which makes sure that validations works in both the UIs (Platform and Portal) even in order guides.
https://community.servicenow.com/community?id=community_article&sys_id=ed24c23ddb024110382a826305961983
Hello Sir,
Thanks a lot. i have implemented the Option 2.
It works as expected.
Cheers !!!!!
Thanks,
Raghav
Hi,
Please help me !!
Could you make the attachment for a particular condition in the catalog item form? I tried the client script on form onsubmit(). But not working, so please help to fix the issue.
Thanks
Arun
Hi everyone
Try this one, I used yes/no variable , and the name of my variable was "multiple_users"
--------------------------------------------------------------