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

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

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'


  }


};