Advanced Reference Qualifier Using a Script Include

Home/Scripting/Script includes/Advanced Reference Qualifier Using a Script Include

Advanced Reference Qualifier Using a Script Include

R

eference qualifiers are a powerful tool that every ServiceNow administrator and consultant should have in their tool belt. They allow you to dynamically filter the available options from a reference field. The ServiceNow wiki has some good documentation on this topic so I won’t re-hash that here. What I do want to address is the topic of Advanced Reference Qualifiers…specifically how to leverage a Script Include instead of a global Business Rule to run your qualifier script.

Reference Qualifier Script Include

Up until recently, the only way to get Advanced Reference Qualifiers to work was to create a global business rule to run the qualifier script. This works great, but it results in a global script that gets loaded all the time when it really isn’t necessary. While this isn’t something that causes any real problems in practice, it could cause performance issues if used to the extreme. The best practice guidance for advanced reference qualifiers should be to use a Script Include rather than a global Business Rule to run the qualifier script. Using a Script Include means that the script only gets loaded and used when you actually need to use it! In this article I’ll show you how this can be done using a common example of filtering the ‘Assignment group’ to display only groups for the ‘Assigned to’ value.

The first piece is the ‘Reference qual’ field value on the dictionary entry of the reference field (Assignment group in this case). The ‘javascript:’ prefix is the same, but you need to reference your Script Include function instead of the business rule function. In this case, I’m using a Script Include named ‘u_backfillAssignmentGroup’. Since these scripts can potentially interfere with each other, it’s best to prefix any of your custom scripts with ‘u_’ or something similar in order to distinguish them from any that ServiceNow may introduce in the future.

javascript:u_backfillAssignmentGroup();

The other piece is obviously the Script Include. Since Script Includes now allow you to use On-Demand functions, your script is identical to the one you would use in a global business rule.

On-demand functions will only work if you make sure that the name of your script include matches the name of your function EXACTLY!
function u_backfillAssignmentGroup() {
   var gp = ' ';
   var a = current.assigned_to;
   
   //return everything if the assigned_to value is empty
   if(!a)
      return;
   
   //sys_user_grmember has the user to group relationship
   var grp = new GlideRecord('sys_user_grmember');
   grp.addQuery('user',a);
   grp.query();
   while(grp.next()) {
      if (gp.length > 0) {
         //build a comma separated string of groups if there is more than one
         gp += (',' + grp.group);
      }
      else {
         gp = grp.group;
      }
   }
   // return Groups where assigned to is in those groups we use IN for lists
   return 'sys_idIN' + gp;
}
By | 2011-06-21T11:45:30+00:00 June 21st, 2011|Categories: Script includes|Tags: , |20 Comments

About the Author:

20 Comments

  1. Tony Fugere June 21, 2011 at 4:39 am - Reply

    Script Includes can be a single function, too. That would reduce the complexity of this a bit. Tom Dilatush’s blog speaks to it. I use “on-demand” functions all the time for Advanced Reference Qualifiers.

    http://community.service-now.com/blog/slightlyloo

    • Mark Stanger June 21, 2011 at 5:42 am - Reply

      You’re right, that’s much easier! I’ve updated the article above accordingly.

  2. sandy December 15, 2011 at 11:59 pm - Reply

    Is it possible that i can dynimically change reference table on a field based on value in the another field?
    for example, if a table has two columns – A and B. A is of type string. B is of type reference. Can I change reference table on B based on value in A?

    • Mark Stanger December 16, 2011 at 4:48 am - Reply

      You would need to use a completely separate field to do that.

  3. alli January 20, 2012 at 2:32 am - Reply

    can you use script include in clientscripts?

    • Jason January 20, 2012 at 3:34 am - Reply

      Hi Alli

      Yes, there is a checkbox that enables client callable..

      • alli January 20, 2012 at 6:01 am - Reply

        thanks

        found it in the wiki,

        Is there a way to use the same script include for client side and server side calls?

        I had to make 2 different script inludes to cater each.

  4. Lofty June 7, 2012 at 7:27 pm - Reply

    I am using a Script Include as a reference qualifier, but it is behaving rather strangely. When I click the magnifying glass, I get the filtered results, if I type ** in the reference field, I get the filtered results, but when I try to type in the value of what I want Firebug reports an error saying “response.responseXML is null”. The reference field filters Business Services related to the company of the caller, I created a m2m table with a related list on both Company as well as Business Services. Any idea why this is happening?

  5. Steve March 11, 2013 at 10:50 am - Reply

    When adding the Tree Picker, is there a way when user pick a member of the group it would be able to populate the Assigned To and Assignment Group in one pick?

    • Mark Stanger March 11, 2013 at 4:53 pm - Reply

      No way to do that currently.

      • salva October 28, 2015 at 4:30 am - Reply

        Is it possible to put an condition in the attribute field? if the assign_to field is not empty then tree_picker=false.

  6. Aritha July 15, 2013 at 9:09 am - Reply

    Can this be used on a Service Catalog variable?

  7. Jef De Coster October 14, 2014 at 1:11 pm - Reply

    Hi All,

    made this a little bit more versatile.
    you can use it on Service Catalog variables as well.
    You can call it from any reference field’s advanced qualifier, as you can specify the reference field targettable

    Tested it out and works…

    Now reviewing setting the default value of the reference field to the first retrieved record, on change of the filtervaluefield

    Any feedback is welcome 😉 (as I’m quite rusty in my scripting, and a newbie in Snow)

    /*
    *-----------------------------------------------------------------------------------------------------------------
    * BEGIN SCRIPT INCLUDE Script
    *-----------------------------------------------------------------------------------------------------------------
    */

        /*
        * Script assembled by using examples and solution provided by:
        * SNGuru - Advanced Reference Qualifier Using a Script Include
        * https://www.servicenowguru.com/scripting/script-includes-scripting/advanced-reference-qualifier-script-include/
        *
        * Script tested in Maxthon Cloud Browser v. 4.4.1.5000
        *
        * Script author : Jef De Coster for Devoteam Belgium
        *
        */

        /*
        *Script specifics:
        *getAdvancedQualifier will get and set the advanced qualification on any reference Field
        *
        *Set Advanced Qualification Filter on any Reference Field.
        *Using 3 variables: "targetTable","filterField","filterValueField to pass thorugh,
        *Will build Qualifier to use in advanced qualifier of a reference field to filter
        *against filterField CONTAINS filterValueField
        *
        * Can be called as for example:
        * javascript:new dvt_ReferenceFieldFunctions().getAdvancedQualifier(targetTable,filterField,filterValueField)
        *   Get the advanced qualifier for referenced table cmdb_ci_hardware, using assigned_to filterfield against caller_id value on current form:
        *       javascript:new dvt_ReferenceFieldFunctions().getAdvancedQualifier("cmdb_ci_hardware","assigned_to","caller_id");
        *   In this example the advanced qualifier of a variable on Record Producer will be set only showing the hardware for the caller.
        */

    var dvt_ReferenceFieldFunctions = Class.create();
    dvt_ReferenceFieldFunctions.prototype = {
        initialize: function() {
        },
        // First real function that will get the Advanced Qualifier
        getAdvancedQualifier : function(targetTable,filterField,filterValueField) {
       
        //Variables
            // answer will contain return value
            var answer = '';
            // includes is used to get the Value from the variables pool from  variable
            var includes = current[filterValueField];
                    //gs.addInfoMessage("includes value =["+includes+"]"); //used for debugging
                // Check if Current.filterValueField isn't "undefined"
                // This is the case if we are using this function from a Service Catalog Item
                // (eg. Record Producer,...)
                if (!includes) {
                    // In case the value is undefined we'll search for a variable
                    // This way this is usable on Service Catalog Item
                    includes = current.variables[filterValueField];
                }
            // GlRec will be used as the gliderecord on the  table
            var GlRec = new GlideRecord(targetTable);
        // Set Query to initiate against the target Table
            // Uses filterField to set against which field to query
            // Uses includes to use as Value to query against
            GlRec.addQuery(filterField,'CONTAINS',includes);
        // Execute Query
            GlRec.query();
        // Loop through recordset an get the sys_id(s)
            while (GlRec.next()) {
                if (answer.length > 0) {
                answer += (',' + GlRec.sys_id);
                }
                else {
                answer = '' + GlRec.sys_id;
                }
            }
        // return the result
            return 'sys_idIN' + answer;
        },
       
        type: 'dvt_ReferenceFieldFunctions'
    };
    /*
    *-----------------------------------------------------------------------------------------------------------------
    * END SCRIPT INCLUDE Script
    *-----------------------------------------------------------------------------------------------------------------
    */
    • Mark Stanger October 14, 2014 at 1:25 pm - Reply

      Thanks for the contribution! Please keep us up-to-date on any modifications or improvements you make.

  8. April June 29, 2015 at 10:34 am - Reply

    Hey Mark, thanks for the article I’m trying to do this exact thing – create a Script Includes to use as a reference qualifier and I’m having issues, can you help?

    Here is what I have so far:

    function u_INC_FilterAssignmentOnDisableTrigger()

    //Create function to use a reference qualifier on the assignment group field on the Incident form to evaluate the value of the checkbox field on the CI and if the box is checked, the Assignment Group will NOT auto-populate on the incident form but rather provide the parent and child assignment groups to select from. If the u_disable_auto_populate_assign box is not checked, auto populate the Incident Assignment group field with the support group assigned to the choice CI
    {
    var current_source = current.cmdb_ci;
    var answer = current.assignment.group;
     
    if(current.cmdb_ci.u_disable_auto_populate_assign == true) //return parent & child assignment groups in the lookup for the CI selected (but don't default populate anything)
      answer= 'parentIN' + current.assignment_group + ',' + current.cmdb_ci.support_group;
     
    if(current.cmdb_ci.u_disable_auto_populate_assign =!true) //Auto Populate the group assigned to cmdb_ci
    answer= 'assignment.cmdb_ci';
     
    return answer;
    }
    return'';
    }

    But I’m still getting the following errors:
    WARNING at line 9: Missing semicolon.

    ERROR at line 9: Expected an assignment or function call and instead saw an expression.

    I’m assuming that after I get this script correct I’d just need to create a dynamic or advance reference qualifier on my assignment group field (ie javascript: u_INC_FilterAssignmentOnDisableTrigger)…… am I right?

    • Mark Stanger June 29, 2015 at 12:03 pm - Reply

      Hey April. These types of questions are probably better suited to the ServiceNow community site. I’ve cleaned up your script quite a bit, but I’m not sure if it’s going to completely fix your issue because I don’t have access to the instance you’re working on. This script should eliminate the errors you’re seeing (and solve several other issues I noticed). If you have further questions please ask on the ServiceNow community site.

      function u_INC_FilterAssignmentOnDisableTrigger(){
          /**Create function to use a reference qualifier on the assignment group field on the Incident form to evaluate the value of the checkbox field on the CI and if the box is checked, the Assignment Group will NOT auto-populate on the incident form but rather provide the parent and child assignment groups to select from. If the u_disable_auto_populate_assign box is not checked, auto populate the Incident Assignment group field with the support group assigned to the choice CI**/
         
          var current_source = current.cmdb_ci;
          var answer = current.assignment.group;
         
          if(current.cmdb_ci.u_disable_auto_populate_assign == true){
              //return parent and child assignment groups in the lookup for the CI selected (but don't default populate anything)
              answer = 'parentIN' + current.assignment_group + ',' + current.cmdb_ci.support_group;
          }
         
          if(current.cmdb_ci.u_disable_auto_populate_assign != true){
              //Auto Populate the group assigned to cmdb_ci
              answer = current.cmdb_ci.support_group;
          }
         
          return answer;
      }
      • April June 29, 2015 at 3:03 pm - Reply

        Thank you!

  9. Andrea Zaffaroni May 26, 2017 at 11:33 am - Reply

    Hi I have a problem: I call a Script Include in the assignmnent_group field of the incidents… but unfortunately I found the same call also in the assignmnent_group of Changes and Problems. How can I fix this problem?

    • Mila Morales September 7, 2017 at 1:02 pm - Reply

      You must create a dictionary entry override for the incident table. In order to do that you need to do the following:
      Configure the dictionary of assignment_group
      Go to the Dictionary Overrides related list
      Click new and specify the table you want to override, in your case the Incident.
      Check the Override reference qualifier and populate the Reference qualifier field with your script include.
      Save the record.

Leave A Comment