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.
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.
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.
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;
}
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…
You’re right, that’s much easier! I’ve updated the article above accordingly.
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?
You would need to use a completely separate field to do that.
can you use script include in clientscripts?
Hi Alli
Yes, there is a checkbox that enables client callable..
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.
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?
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?
No way to do that currently.
Is it possible to put an condition in the attribute field? if the assign_to field is not empty then tree_picker=false.
I don’t believe so.
Can this be used on a Service Catalog variable?
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://servicenowguru.wpengine.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
*-----------------------------------------------------------------------------------------------------------------
*/
Thanks for the contribution! Please keep us up-to-date on any modifications or improvements you make.
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:
//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?
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.
/**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;
}
Thank you!
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?
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.