Require attachment for catalog item in Service Portal

mspeirs
Mega Expert

We are preparing to make Service Portal live and going through our service catalog items to make sure everything works ok. One challenge we have is being able to require an attachment before submission. We want to do this always for some forms and conditionally on others. We were using one solution that relied on the DOM but we know that functionality is restricted in the Service Portal. I have seen some solutions but I wanted something simpler that required fewer modifications of OOB code or widgets and would be flexible and easy to reuse. What I came up with is not a perfect solution but it works for now.

We have a global UI Script with reusable functions for catalog items. It prevents having to maintain functions in multiple places and makes them available for all catalog items. Lets name this global UI Script GlobalCatalogItemFunctions. This script needs to be included in your Service Portal via the Theme. Go to Service Portal > Portals and select your portal. Then click the reference icon next to the Theme field to go to its record. There is a related list called JS Includes. Create a new one (Source: UI Script) and set the UI Script to GlobalCatalogItemFunctions. You can set the display name to that as well. Save. The functions in the UI Script will now be available for use in Catalog client scripts. This is the function I am using for getting the attachment count:

UI Script: GlobalCatalogItemFunctions

function getSCAttachmentCount() {

  var length;

  try {

  length = angular.element("#sc_cat_item").scope().attachments.length;

  } catch(e) {

  length = -1;

  }

  return length;

}

This is an onSubmit script I am using for a catalog item:

function onSubmit() {

  try { //Works in non-portal ui

  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;

  }

  } catch(e) { //For Service Portal

  var count = getSCAttachmentCount();

  if(count <= 0) {

  alert('You must attach the completed form before submitting this request.');

  return false;

  }

  }

}

Notice in the onSubmit script I used a try/catch block and the first part works in the full UI but not in the Service Portal. In the portal, the document.getElementById... part will not work, but our catch statement performs the method that will work in the portal by calling the getSCAttachmentCount() function which is in our included ui script. That function accesses the angular scope of the catalog item which has an array of the attachments. We just want the count so we use the length attribute. There's no guarantee this will work in the future but for now it will get the job done. It would be nice if there were a function to get attachment information out-of-the-box.

For reference:

Is it possible to require a user to add an attachment before submitting a catalog item?

Catalog service making Mandatory Attachment both application and SP

Service Portal UI Script or Reusable functions in Client Scripts

73 REPLIES 73

edans
Tera Contributor

This is exactly what I was looking for and works a treat, thank you!


Abhinay Erra
Giga Sage

Great stuff on the UI script


Thomas Wright-1
Mega Expert

Thanks Michael.


I'm trying to use a similar UI Script in a scoped application, with a scoped portal.


I've added the UI script to my portal's theme, and I can see it gets loaded in to my sources. But it throws an error every time the UI script is loaded:


Uncaught ReferenceError: ScopedGlideAjaxGenerator is not defined



I can see that the system has added ScopedGlideAjaxGenerator itself to my script, so I'm not sure there's much I can do about it.


find_real_file.png



Technically I don't need this code to be shared across the portal so I also tried just running in a client script:


angular.element("#funding_record").scope().attachmentHandler.getAttachmentList.length


But angular itself is undefined from the client script (but not the console), I'm guessing that's why the UI Script is required.



Sadly I'm thinking I will just have to do a server side check for any attachments and then force the user to resubmit if there aren't any.



For reference, my UI Script is as below, note the ScopedGlideAjaxGenerator is not included:


var x_braoi_funding = x_braoi_funding || {};



x_braoi_funding.servicePortalFunctions = (function() {


  "use strict";



/* set your private variables and functions here. For example:


  var privateVar = 0;


  function private_function() {


  return ++privateVar;


  }


*/



/* Share variables between multiple UI scripts by adding them to your scope object. For example:


  x_braoi_funding.sharedVar = 0;



Then access them in your scripts the same way. For example:


  function get_shared() {


  return x_braoi_funding.sharedVar;


  }


*/



  return {



/* set your public API here. For example:


  incrementAndReturnPrivateVar: function() {


  return private_function();


  },


*/


  getFundingAttachmentCount: function() {


  var length;


  try {


  length = angular.element("#funding_record").scope().attachmentHandler.getAttachmentList.length;


  } catch(e) {


  length = -1;


  }


  return length;


  },


 


  type:   "servicePortalFunctions"


  };


})();


Michael Kaufman
Giga Guru

Help for others...I had to logout and cleared the cache for this to take effect.



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;


}



Select your Portal > Theme


Create New JS Theme


Display Name: GlobalCatalogItemFunctions


UI Script: GlobalCatalogItemFunctions




Catalog 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;


  }


  }


}