Calling a Script Include from a Scoped UI Action condition

Katie A
Mega Guru

I am creating a new Scoped application. I want to call a Script Include from the CONDITION field of a UI Action.

Basically, I want the UI Action to appear only if the result of the script include is true.

I am unable to call the Script Include from the UI Action condition.

I have tried creating a Global script include and calling it in the UI Action condition with the fully-qualified name. I also tried making the Script Include in the SAME scope as the application. In both cases there are error messages in the log.

Script Include

Accessible from: All application scopes

Client Callable

API Name GLOBAL:

global.hasAttachments

API Name SCOPED :

x_myscp_infosec_sc.hasAttachments

var hasAttachments = Class.create();

hasAttachments.prototype = {

      initialize: function() {

      },

  countAttachments: function() {

  var attachments = new GlideRecord('sys_attachment');

  attachments.addQuery('table_sys_id',current.sys_id);

  attachments.query();

  if (attachments.hasNext()) {

  gs.info("Attachment file name: " + attachments.file_name + " created on: " + attachments.sys_created_on.getDisplayValue());

  return true;

  }

      type: 'hasAttachments'

  }

};

UI Action condition

Global

global.hasAttachments.countAttachments()==true

Scoped

x_myscp_infosec_sc.hasAttachments.countAttachments()==true

Error

org.mozilla.javascript.EcmaError: undefined is not a function.

Caused by error in UI Action: 'Send Attachments' at line -1

1 ACCEPTED SOLUTION

coryseering
ServiceNow Employee
ServiceNow Employee

Oops, I missed this:



if (attachments.hasNext()) {    


      gs.info("Attachment file name: " + attachments.file_name + " created on: " + attachments.sys_created_on.getDisplayValue());    


      return true;    


}



Should be:


if (attachments.next()) {    


      gs.info("Attachment file name: " + attachments.file_name + " created on: " + attachments.sys_created_on.getDisplayValue());    


      return true;    


}



Otherwise you wont be moving to the actual record in the result set when you try to log the values.



Also, use the new keyword in your condition:


new global.hasAttachments().countAttachments(current);



You should be able to put this in your UI Action's scope, and simply mark it accessible to all application scopes to make it accessible to them.



hasAttachments is a fairly generic name, and it's possible there is something in the global execution context that has this name. I recomemnd trying to create the include with a more distinct name like "AttachmentUtility" or "CheckAttachment"- something you can be sure is not already defined in a global business rule, another Script Include, or provided by the base system.


View solution in original post

7 REPLIES 7

srinivasthelu
Tera Guru

Hi Kathryn,



gr is not defined in the function. I think that must be throwing the error in the log.



  1. countAttachments: function() {  
  2.   var attachments = new GlideRecord('sys_attachment');  
  3. gr.addQuery('table_sys_id',current.sys_id);   // gr not defined here.
  4.   gr.query();  
  5.   if (gr.hasNext()) {  
  6.   gs.info("Attachment file name: " + attachments.file_name + " created on: " + attachments.sys_created_on.getDisplayValue());  
  7.   return true;  
  8.   }  
  9.       type: 'hasAttachments'  
  10.   }  

I pasted the wrong version of the code. I have pasted the current version in the original submission. The error occurs in the log even with the code above. Thanks for checking.


coryseering
ServiceNow Employee
ServiceNow Employee

Hi Katharyn,



You have a couple of errors here.


Your Script Include is written in the classic Prototype Class style, meaning you need to create a new instance whenever you use it:


global.hasAttachments().countAttachments()



Second, "current" might not be defined in the context of the Script Include. You should explicitly pass in the record:



global.hasAttachments().countAttachments(current);



And expect to receive the record in your method definition:



var hasAttachments = Class.create();


hasAttachments.prototype = {


      initialize: function() {


      },


      countAttachments: function(record) {


      var attachments = new GlideRecord('sys_attachment');


      attachments.addQuery('table_sys_id',record.sys_id);


      attachments.query();


      if (attachments.hasNext()) {


          gs.info("Attachment file name: " + attachments.file_name + " created on: " + attachments.sys_created_on.getDisplayValue());


          return true;


      }


      type: 'hasAttachments'


  }


};



You can put the Script Include in the same scope as the UI Action, and leave off the scope identifier:


new hasAttachments().countAttachments(current);



I believe this will solve your issue.


Thanks Cory!



I would like to have this script include in the Global scope so I can use it for other applications.


I have made the adjustments as you suggested. There is an error regarding undefined value properties:



org.mozilla.javascript.EcmaError: The undefined value has no properties.


Caused by error in Script Include: 'PrototypeServer' at line 4



UI Action Condition


global.hasAttachments().countAttachments(current)==true



Script Include


var hasAttachments = Class.create();


hasAttachments.prototype = {


      initialize: function() {


      },


      countAttachments: function(record) {


      var attachments = new GlideRecord('sys_attachment');


      attachments.addQuery('table_sys_id',record.sys_id);


      attachments.query();


      if (attachments.hasNext()) {


          gs.info("Attachment file name: " + attachments.file_name + " created on: " + attachments.sys_created_on.getDisplayValue());


          return true;


      }


      type: 'hasAttachments'


  }


};