Reference field Archives - ServiceNow Guru https://servicenowguru.com/tag/reference-field/ ServiceNow Consulting Scripting Administration Development Tue, 28 May 2024 21:23:00 +0000 en-US hourly 1 https://wordpress.org/?v=6.8.2 https://servicenowguru.com/wp-content/uploads/2024/05/cropped-SNGuru-Icon-32x32.png Reference field Archives - ServiceNow Guru https://servicenowguru.com/tag/reference-field/ 32 32 Adding Referenced Records Without Leaving the Form https://servicenowguru.com/ui-macros/adding-referenced-records-leaving-form/ https://servicenowguru.com/ui-macros/adding-referenced-records-leaving-form/#comments Thu, 24 Mar 2011 11:13:15 +0000 https://servicenowguru.wpengine.com/?p=3508 One problem I’ve seen a few times is the need to create a new record on the fly in order to populate it into a reference field. This problem recently came up for me with a client I’m working with so I decided to come up with a good solution. An example scenario would be

The post Adding Referenced Records Without Leaving the Form appeared first on ServiceNow Guru.

]]>
One problem I’ve seen a few times is the need to create a new record on the fly in order to populate it into a reference field. This problem recently came up for me with a client I’m working with so I decided to come up with a good solution. An example scenario would be a technician filling out an incident record for a user that doesn’t yet exist in the system. At first glance, the solution seems simple enough…simply navigate to the user form and create the new user, then create your incident record. While that can be done, it’s not always so simple. What if the technician has just spent several minutes filling out the incident and then realizes the caller doesn’t exist? The user would then have to navigate away from that incident record and lose all of the changes, or open an entirely new browser window to create the user and then return and populate the field.

Fortunately, there is a better way if you know how to leverage UI Macros and GlideDialogWindow QuickForms. This article shows a solution that you can use for any ‘sys_user’ reference field in your system. It can also be easily modified and applied to other reference fields as well.

GlideDialogWindow-Add User

The first step in this solution is to create a new UI Macro that can be associated to the reference field(s) that you want to be able to create new records from. The macro I’ve created here is very loosely based on an out-of-box macro, but also has three very important differences.

  1. The first difference is that it uses standard ‘A’ and ‘IMG’ html tags to display the macro icon rather than the ‘g:reference_decoration’ tag that is normally used for reference field macros. The reason for this is that we need the macro to always be visible…especially if the reference field doesn’t have anything in it. By design, the ‘g:reference_decoration’ tag only shows the macro if something is populated in the reference field.
  2. The other change is what the ‘onClick’ event (the ‘addEditUserPop’ function) does when the macro icon is clicked. It opens a GlideDialogWindow quickform to display either a new record window (to add a new record if the field is empty when the macro is clicked) or an edit window to edit the record (if the field is populated when the macro is clicked). Check this article out if you need more information about how GlideDialogWindow quickforms work.
  3. Lastly, the callback function (the ‘setUserField’ function) gets called after the dialog is submitted and populates the reference field with the newly-added or edited record.

You can set up the UI Macro like this…

‘add_edit_user’ UI Macro
Name: add_edit_user
Description:
Show add/edit user macro icon on a reference field
Activate by:
– Setting the active field in this macro to true
– Adding the attribute to a dictionary field: ref_contributions=add_edit_user
XML:

<!--?xml version="1.0" encoding="utf-8" ?-->



<a id="${jvar_n}"></a>
<img title="${gs.getMessage('Add/Edit User')}" src="images/icons/user_profile.gifx" alt="${gs.getMessage('Add/Edit User')}" border="0" />
<script>
      //OnClick function for UI macro
      function addEditUserPop(reference){
         var s = reference.split('.');
         var referenceField = s[1];
         var v = g_form.getValue(referenceField);

         //If user field is empty then pop open an 'Add User' dialog
         if(v == ''){
            var dialog = new GlideDialogForm('Add User', 'sys_user', setUserField);
            dialog.setSysID('-1'); //Pass in -1 to create a new record
         }
         //Else pop open an 'Edit User' dialog for the populated user record
         else{
            var dialog = new GlideDialogForm('Edit User', 'sys_user', setUserField);
            dialog.setSysID(v); //Pass in reference sys_id to edit record
         }
         dialog.addParm('sysparm_view', 'default'); //Specify a form view
         dialog.addParm('sysparm_form_only', 'true'); //Remove related lists
         dialog.render(); //Open the dialog

         //Callback function executed from dialog submit
         function setUserField(action, sys_id, table, displayValue){
            //Set the user field with the popup user
            g_form.setValue(referenceField, sys_id);
         }
      }
   </script>

XML (Fuji version):

<!--?xml version="1.0" encoding="utf-8" ?-->





<a>
<span id="${jvar_n}" class="btn btn-default icon-add-circle" title="${gs.getMessage('Add User')}">
</span>
</a>

<script>
         //OnClick function for UI macro
         function addEditUserPop(reference){
            var s = reference.split('.');
            var referenceField = s[1];
            var v = g_form.getValue(referenceField);

            //If user field is empty then pop open an 'Add User' dialog
            if(v == ''){
               var dialog = new GlideDialogForm('Add User', 'sys_user', setUserField);
               dialog.setSysID('-1'); //Pass in -1 to create a new record
            }

            //Else pop open an 'Edit User' dialog for the populated user record
            else{
               var dialog = new GlideDialogForm('Edit User', 'sys_user', setUserField);
               dialog.setSysID(v); //Pass in reference sys_id to edit record
            }
            dialog.addParm('sysparm_view', 'add_user'); //Specify a form view
            dialog.addParm('sysparm_form_only', 'true'); //Remove related lists
            dialog.render(); //Open the dialog

            //Callback function executed from dialog submit
            function setUserField(action, sys_id, table, displayValue){
               //Set the user field with the popup user
               g_form.setValue(referenceField, sys_id);
            }
         }
      </script>


Once you’ve set up the UI Macro, you need to add the appropriate attribute to the reference field so that the macro will be displayed. In order to do that, you simply need to personalize the dictionary for your reference field and add the ‘ref_contributions=add_edit_user‘ attribute to the ‘Attributes’ field on the dictionary. If you have multiple ‘ref_contributions’ attributes, they should be separated by a semicolon and this macro will look best if it is the first macro listed for the field.

That’s it! Here are a few screenshots of the finished product!

Add/Edit User UI Macro
AddEditUser-Macro

Add User Dialog Window
GlideDialogWindow-Add User

Edit User Dialog Window
GlideDialogWindow-Edit User

Reference field populated with new user

The post Adding Referenced Records Without Leaving the Form appeared first on ServiceNow Guru.

]]>
https://servicenowguru.com/ui-macros/adding-referenced-records-leaving-form/feed/ 35
Fixing the Fatal Flaw of Before Query Business Rules https://servicenowguru.com/business-rules-scripting/fixing-before-query-business-rules-flaw/ https://servicenowguru.com/business-rules-scripting/fixing-before-query-business-rules-flaw/#comments Wed, 05 Jan 2011 16:30:07 +0000 https://servicenowguru.wpengine.com/?p=3137 While this customization may still be necessary in certain situations, ServiceNow handles this issue in Aspen builds or later without any customization. I’ve written before on SNCGuru about how ‘before query’ business rules can (and should) be used to secure row-level read access to records in Service-now. While this usually works perfectly, there is one

The post Fixing the Fatal Flaw of Before Query Business Rules appeared first on ServiceNow Guru.

]]>
While this customization may still be necessary in certain situations, ServiceNow handles this issue in Aspen builds or later without any customization.

I’ve written before on SNCGuru about how ‘before query’ business rules can (and should) be used to secure row-level read access to records in Service-now. While this usually works perfectly, there is one issue that I’ve seen come up continually that there hasn’t been a good fix for. Over the past few weeks, I’ve seen several incidents and questions about inactive users disappearing from reference fields in Service-now systems. You may have noticed this yourself when you’ve de-activated users or groups in your system. The culprit in these cases is the ‘user query’ or ‘group query’ business rule.

The recommended (but really not great) solution up until this point is to turn the business rule off and use a reference qualifier on the reference field that you need to see the user in. The reason this solution is a bad one is that there are over 300 user reference and list fields in your system! Not only is that a big pain (and a bad idea) to add that reference qualifier to all of those places, but it also does nothing for the countless places (modules, filters, reports, etc.) that have UI elements that work like reference fields but cannot be filtered with a reference qualifier! This isn’t a new problem, but I’ve come up with a new (and extremely simple) solution.

‘Before Query’ business rules usually serve one of two purposes…

  1. Preventing read access to a group of records (security)
  2. Removing records from view so you don’t have to look at irrelevant data in lookups

The problem I’ll touch on in this post arises when you use ‘before query’ business rules to deal with the second point above. A prime example is the ‘user query’ business rule on the ‘User (sys_user)’ table out-of-box. That business rule looks like this…

if (!gs.hasRole("admin")) {
   current.addQuery("active", "true");
}

What this business rule says, in essence, is that users with the ‘admin’ role can read all user records in the system, and everybody else can only read active user records. On the surface, this seems like it’s exactly what you want. There’s no reason for inactive user records to be getting in the way all of the time for your technicians and end users to have to filter through. Even if they can deal with that extra nuisance, you don’t want somebody accidentally logging a ticket for, or assigning a CI to, the ‘John Smith’ that left your company 2 years ago.

Although the goal is a good one, the end result can actually end up being a big mess. If you’ve ever had one of your ‘itil’ users open up an old incident for that long-since-inactive ‘John Smith’ account you’ve seen what happens. ANY of the potentially thousands of reference field entries or filter conditions that reference that inactive user will appear to be blank for anybody without the ‘admin’ role!

Here’s an example screenshot I created of an incident record. In this case, the same user (ITIL User) opened up an incident and is also the Caller and Assignee. Right after the incident was created however, ITIL User was made inactive. The next non-admin user to open the incident would see a record with blank entries in reference fields wherever the user was listed. The values (sys_ids) are still there, but the system isn’t able to query for the inactive user because the user performing the query isn’t an admin! This results in what looks like an empty field because there isn’t a display value shown for the referenced record.

Service-now user_query Problem

How to fix the problem…

So, the obvious question becomes, “How do I fix it?”. The fix is actually a pretty simple one, but I think it helps to understand how ‘before query’ business rules work first. When the system performs a query to display a list of records, a lookup filter, or a reference field display value, it constructs the query the same way you would if you were to write a GlideRecord query in your own script.

current = new GlideRecord('sys_user');
current.addQuery(QUERY_CONDITIONS_HERE);
current.query();

A ‘before query’ business rule on a given table gets run immediately before the ‘current.query()’ line…when the query actually gets executed. So a ‘before query’ business rule gets run before the query execution, but NOT before the initial query conditions get built. What this means is that you have a chance in your ‘before query’ business rule to evaluate whatever query conditions exist and make certain decisions about how to modify the query!
For this particular case, it means that I can check to see if the query is a generic query to bring up a list, or a specific query on a SYS_ID value to pull up a specific record. When the system queries for user records to display in reference fields, filters, and report conditions the query actually looks like this at the time it hits the ‘user_query’ business rule.

current = new GlideRecord('sys_user');
current.addQuery('sys_id', USER_RECORD_SYS_ID);

Notice the absence of the ‘current.query()’ line. When a ‘before query’ business rule is run, that line hasn’t happened yet. Poking around the GlideRecord API a bit, I was able to find a method that allowed me to get the encoded query and evaluate it. What I discovered is that any time the system makes queries for reference fields, etc. the encoded query string always starts with ‘sys_id=’.

So, here’s the fix. Simply wrap your ‘addQuery’ lines in your ‘before query’ business rule in an ‘if’ statement as shown below. Any specific record queries (like those for reference fields, filters, and report conditions) will be allowed. Any other list query (like a standard list of users in a record list or reference popup) will be filtered just like normal!

if (!gs.hasRole("admin")) {
   //Check to see if this is a query for a specific ID
   if (current.getEncodedQuery().indexOf('sys_id=') != 0) {
      current.addQuery("active", "true");
   }
}

The post Fixing the Fatal Flaw of Before Query Business Rules appeared first on ServiceNow Guru.

]]>
https://servicenowguru.com/business-rules-scripting/fixing-before-query-business-rules-flaw/feed/ 22
Creating an Alias for Reference Field Searches https://servicenowguru.com/client-scripts-scripting/creating-alias-reference-field-searches/ https://servicenowguru.com/client-scripts-scripting/creating-alias-reference-field-searches/#comments Mon, 03 May 2010 13:26:51 +0000 https://servicenowguru.wpengine.com/?p=1662 A while ago I wrote about some of the different ways to customize the autocomplete search behavior for a reference field. I saw a forum post the other day where the poster asked if it was possible to create aliases for records so that they could be searched on. For example, what if you had

The post Creating an Alias for Reference Field Searches appeared first on ServiceNow Guru.

]]>
A while ago I wrote about some of the different ways to customize the autocomplete search behavior for a reference field. I saw a forum post the other day where the poster asked if it was possible to create aliases for records so that they could be searched on. For example, what if you had a CI called ‘ABC’ but everybody knew it by the name of ‘XYZ’? While support for this type of searching isn’t really built into Service-now, it is possible to add this kind of behavior to a reference field. If the CI just had a single alias, you could probably just customize the display value and do a ‘contains’ autocomplete search as described in the article previously. For this specific scenario I think that there might be a better way to accomplish the same thing.


This solution relies on 2 simple customizations. For the purposes of this article, I’ll assume that we want to provide aliases for a few of the records in the Configuration Item (cmdb_ci) table. The first step is to create a new field on the ‘cmdb_ci’ table called ‘Alias for’. This field should be a reference field to the same table you create the field on…in this case the field needs to reference ‘cmdb_ci’. The purpose of the field is so that you can create a CI record that has no other purpose other than to point to another CI record. Your alias becomes a CI and it points to the true CI populated in the ‘Alias for’ field.

Once you have the ‘Alias for’ field set up and you have an alias populated, the next step is to create a client script to populate the true CI value when an alias is used. In this case, we want to set up the alias functionality for the ‘Configuration item’ field on all Task tables (Incident, Problem, Change, etc.). Our client script should be set up on the task table with the following settings…

Populate CI from Alias Client Script
The purpose of the client script is to wait for the Configuration item field to change, check the populated CI to see if it has any value in the ‘Alias for’ field (indicating that it is just an alias) and populate the true CI value from the ‘Alias for’ field.
Name: Populate CI from Alias
Table: Task
Type: onChange
Field name: Configuration item
Inherited: True
Script:

function onChange(control, oldValue, newValue, isLoading) {
//If the page isn't loading
if (!isLoading) {
//Hide any field message on the 'cmdb_ci' field
g_form.hideFieldMsg('cmdb_ci');
//If the new value isn't blank
if(newValue != '') {
//Check to see if the CI is an alias
var rec = g_form.getReference('cmdb_ci');
if(rec.u_alias_for != ''){
//Populate the value of the true CI
g_form.setValue('cmdb_ci', rec.u_alias_for);
g_form.showFieldMsg('cmdb_ci','CI populated from alias');
}
}
}
}

The post Creating an Alias for Reference Field Searches appeared first on ServiceNow Guru.

]]>
https://servicenowguru.com/client-scripts-scripting/creating-alias-reference-field-searches/feed/ 8
Multiple Reference Display Values Per Table https://servicenowguru.com/system-definition/multiple-reference-display-values/ https://servicenowguru.com/system-definition/multiple-reference-display-values/#comments Tue, 06 Apr 2010 13:11:42 +0000 https://servicenowguru.wpengine.com/?p=1263 When working with reference fields, it is really important to understand how the display value for the reference field works.  The display value for a reference field is what the end user actually sees when they search in a reference field to produce an autocomplete drop down and what they can see when a reference

The post Multiple Reference Display Values Per Table appeared first on ServiceNow Guru.

]]>
When working with reference fields, it is really important to understand how the display value for the reference field works.  The display value for a reference field is what the end user actually sees when they search in a reference field to produce an autocomplete drop down and what they can see when a reference field gets populated.  Information about reference fields and reference field display values can be found here.

Some questions about display values that I hear very often are “How do I show information from more than one field for the display value?” or “Can I have different display values on 2 reference fields that reference the same table?”.  The limiting factor when answering these questions is that you’re limited to a single searchable display value per referenced table. What this means is that EVERY reference field that references a particular table needs to use that table’s display value so you cannot mix and match between reference fields.  There are a couple of options that can be used to provide a bit more information to the user in these scenarios however.

The way I typically approach this type of requirement is to create a new calculated field that is a composite of the fields that I want to search on. Then I make that field my display value for that table. A good example of this is the ‘Name’ field on the user table. What you see is the full name of a user. If you look at the dictionary entry for that field however, you’ll see that it is actually a calculated field that pulls together the values from the First name, Last Name, and Middle Name fields.
Once this is done (and I’ve updated all of the records in the table so that my calculation gets stored on each record) I can make this field my display field for the table and change how searches are performed on references to that table. By using a ‘Contains’ type of search instead of the default ‘Starts with’ type of search against the display value for a table I can effectively search on multiple terms in the same field since I’ve included them in the same display value string. This article explains how to set up a ‘Contains’ autocomplete search for a particular table.

Customizing Autocomplete Search Behavior

Another useful option for reference fields is to display additional attributes in the autocomplete drop-down. These attributes aren’t searchable and they won’t show up as the display value when the field gets populated, but they do make it very simple to display more than just the display value in an autocomplete.

Display Additional Reference Field Attributes

The post Multiple Reference Display Values Per Table appeared first on ServiceNow Guru.

]]>
https://servicenowguru.com/system-definition/multiple-reference-display-values/feed/ 8