Maik Skoddow
Tera Patron
Tera Patron

find_real_file.png

The following lines may not mean a great gain in knowledge, and I am sure that one or the other author has already written about this topic here in the community before me. However, since the result is quite interesting, it was worth a new article for me.

        
Table of Contents

Challenge

find_real_file.pngThe Watch list is the best known representative of the "Glide List" field type, which many users struggle with, as the many questions about it here in the community show. Under the hood, however, this field type is quite simply a comma-separated enumeration of Sys IDs or email addresses.

While this makes this field type perfect for data processing, in practice it comes with a few downsides. For example, in the list view, the search field in the table header is disabled. Furthermore, all values are written one after the other separated by a comma, which makes the list difficult to read. And last but not least, the list is truncated after 40 characters.

The Watch list should be presented a bit more user-friendly and also be enhanced with a few useful features. For example, it would be nice to be able to see at a glance if the specified user is disabled and/or locked out. Also, the names and email addresses should be linked so that clicking on them either opens the record view or an email client.

 

Solution

ServiceNow unfortunately doesn't know the concept of custom renderers (at least I haven't been able to find one yet). For this reason we need a new field that does not get the content from the user input but calculates it (so-called "Calculated Field"). 

For this purpose we can go to System Definition > Dictionary and create a new field for the table "task" as follows (the important configurations are marked with red arrows):

find_real_file.png

 

At the field "Calculation" the following script has to be entered:

(function calculatedFieldValue(current) {
  if (current.watch_list && current.watch_list.toString().length > 0) {
    var grUser     = new GlideRecord('sys_user');
    var arrOutput  = [];
    var arrUsers   = [];
    var arrEmails  = [];

    //write the sys IDs and the email addresses into two separate arrays
    current.watch_list.split(',').forEach(function(value) {
      if (value.indexOf('@') > -1) {
        arrEmails.push(value);
      }
      else if (value.length == 32) {
        arrUsers.push(value);
      }
    });

    //the watch list contains Sys IDs of sys_user records
    if (arrUsers.length > 0) {
      grUser.addQuery('sys_idIN' + arrUsers.join(','));
      grUser.query();

      while (grUser.next()) {
        var arrStyles = [];

        arrOutput.push('<a class="linked" ');

        if (grUser.locked_out) {
          arrStyles.push('color: red;');
        }

        if (!grUser.active) {
          arrStyles.push('text-decoration: line-through;');
        }

        if (arrStyles.length > 0) {
          arrOutput.push('style="');
          arrOutput.push(arrStyles.join(''));
          arrOutput.push('" ');
        }

        arrOutput.push('href="sys_user.do?sys_id=');
        arrOutput.push(grUser.getUniqueValue());
        arrOutput.push('" target="blank">');
        arrOutput.push(grUser.getDisplayValue());
        arrOutput.push('</a><br/>');   
      }
    }

    //the watch list contains email addresses
    arrEmails.forEach(function(strEmail) {
      arrOutput.push('<a href="mailto:');
      arrOutput.push(strEmail);
      arrOutput.push('">');
      arrOutput.push(strEmail);
      arrOutput.push('</a><br/>');           
    });

    //wrap generated HTML code into a [code][/code] block to be rendered accordingly
    return '[code]' + arrOutput.join('') + '[/code]';
  }

  return ''; 

})(current);

 

That code performs the following steps:

  1. Split the value of the "Watch list" field into an array.
  2. Iterate that resulting array and separate the Sys IDs as well as the email addresses into two new arrays.
  3. Build the resulting HTML code by:
    • Iterating over the sys_user records and formatting the user's display name depending on whether the user account is disabled and/or locked out.
    • Iterating over the email addresses and building "mailto:" links.
  4. Wrap the resulting HTML code into a [code] [/code] block, which is necessary for the correct interpretation of the HTML code by ServiceNow

 

The resulting list looks as follows

find_real_file.pngColumn is searchable in the table head.

User names and email addresses are linked.

Visual indicators for deactivated (crossed out) and/or locked out (red color) accounts.

Each value is written in a new line.

Nothing is cut off.

 

Limitations

The given approach really only works for the list views in the UI16. In other experiences, the content is masked and printed as it is:

find_real_file.png

 

And it is also not helpful to place the new field on the record form:

find_real_file.png

Comments
Laszlo Balla
Mega Sage
Mega Sage
Very creative, thanks for sharing in such detail!
anandman3g
Tera Contributor

Thanks for sharing. Indeed useful feature

Version history
Last update:
‎12-31-2021 12:38 PM
Updated by: