How to Filter Reference Field Based on Other Table's Field?

E555
Tera Guru

Hi Community,

 

I'm trying to filter the options in a reference field (target_user) in a ServiceNow catalog item. Here are the requirements and what I've tried so far:

Requirements:

  1. The sys_user.object_id must not be empty.
  2. The sys_user must be active (Active = true).
  3. Users with u_status set to 1, 2, 3, or 4 in the u_history_table must be excluded. (u_status is a choice field with 4 options, and a record is created for each user with one column referring to the sys_user table).

What I Have Tried:

  1. Script Include:

    • Created a Script Include named Filter_user_bu_Status to retrieve users with u_status set to 1, 2, 3, or 4.
    • The Script Include works correctly in the Log and retrieves the correct user`s sys_id to be excluded.

 

var Filter_user_bu_Status = Class.create();
Filter_user_bu_Status.prototype = Object.extendsObject(AbstractAjaxProcessor, {
    getExcludedUsers: function() {
        var excludedUserList = [];
        var gr = new GlideRecord('u_history_table');
        
        gr.addQuery('u_status', 'IN', '1,2,3,4');
        gr.query();
        while (gr.next()) {
            var userSysId = gr.u_user.toString();
            if (userSysId) {
                excludedUserList.push(userSysId);
            }
        }

        return new JSON().encode(excludedUserList);
    }
});

 

  • Reference Qualifier:

    • Used a Reference Qualifier to filter out the users based on the conditions.
    • Attempted to use both g_form.setDependentFieldFilter and a script directly in the Reference Qualifier, but neither approach worked as expected.

    Reference Qualifier Script:

 

(function() {
    var excludedUsers = [];
    var ga = new GlideAjax('Filter_user_bu_Status');
    ga.addParam('sysparm_name', 'getExcludedUsers');
    var response = ga.getXMLWait();  // Use synchronous call to get the response
    var answer = response.documentElement.getAttribute("answer");
    excludedUsers = JSON.parse(answer);

    var filterString = 'active=true^object_idISNOTEMPTY';
    if (excludedUsers.length > 0) {
        filterString += '^sys_idNOT IN' + excludedUsers.join(',');
    }

    return filterString;
})();

 

  •  

    Client Script:

    • Also tried using a Client Script to filter the options, but it didn't work as expected either.

 

function onLoad() {
    var ga = new GlideAjax('Filter_user_bu_Status');
    ga.addParam('sysparm_name', 'getExcludedUsers');
    ga.getXMLAnswer(function(response) {
        var excludedUserList = JSON.parse(response);
        g_form.clearOptions('target_user'); // Clear existing options
        g_form.addOption('target_user', '', '--Select a user--'); // Add default option

        var gr = new GlideRecord('sys_user');
        gr.addQuery('active', true);  // Only active users
        gr.addQuery('object_id', '!=', '');  // Users with non-empty object_id
        gr.query();
        var addedUsers = [];  // For debug
        while (gr.next()) {
            var userId = gr.sys_id.toString();
            if (!excludedUserList.includes(userId)) {
                g_form.addOption('target_user', userId, gr.name.toString());
                addedUsers.push(userId);  // For debug
            } else {
                g_form.addInfoMessage('Excluded user not added: ' + userId); // For debug
            }
        }

        g_form.addInfoMessage('Excluded users: ' + JSON.stringify(excludedUserList)); // For debug
        g_form.addInfoMessage('Added users: ' + JSON.stringify(addedUsers)); // For debug
    });
}
​

 

Table Structure: The u_history_table has the following columns:

  • u_user: A reference to the sys_user table.
  • u_status: A choice field with values 1, 2, 3, and 4.

A record is created in u_history_table for each user (u_user).

Issues:

  • The Reference Qualifier is not filtering the users as expected.
  • All users are still being displayed in the target_user field despite the filters.

Request:

  • I need new ideas to achieve the requirements or help to fix the scripts I have tried to meet the requirements.
  • Any suggestions or best practices for achieving this filtering in ServiceNow.

Thank you in advance for your help!

 

3 REPLIES 3

Jake Sadler
Kilo Sage

Hi @E555 ,

 

The reference qualifier should do this.

 

You are treating it as a client side but it is a server side script.

 

Create a server side script include and use this script 

 

 var excludedUserList = [];
        var gr = new GlideRecord('u_history_table');
        
        gr.addQuery('u_status', 'IN', '1,2,3,4');
        gr.query();
        while (gr.next()) {
            var userSysId = gr.u_user.,sys_id.toString();
            if (userSysId) {
                excludedUserList.push(userSysId);
            }
        }
var query = "sys_idNOTIN"+excludedUserList.toString();
return query;

 

In the ref qual call the script include new global.scriotIncludeName().functionName(current);

 

Use current dot walking to push any values you want to the script include

Thank you for your response.

I tried it, but the filtering is still not working for the "target_user" options. The API Name for the Script Include is correctly set to "global.Filter_user_bu_Status".

Additionally, I received the following log waring:
"Invalid query detected, please check logs for details [Unknown field null in table sys_user]".

 

Script Include:

var Filter_user_bu_Status = Class.create();
Filter_user_bu_Status.prototype = Object.extendsObject(AbstractAjaxProcessor, {
    getExcludedUsers: function() {
        var excludedUserList = [];
        var gr = new GlideRecord('u_history_table');
        
        gr.addQuery('u_status', 'IN', '1,2,3,4');
        gr.query();
        while (gr.next()) {
            var userSysId = gr.u_user.sys_id.toString();
            if (userSysId) {
                excludedUserList.push(userSysId);
            }
        }

        var query = "sys_idNOTIN" + excludedUserList.toString();
        return query;
    }
});

Reference Qualifier:

new global.Filter_user_bu_Status().getExcludedUsers(current);

I hope this helps to clarify the issue. Please let me know if there are any other suggestions or corrections. Thank you!

@E555 The query NOTIN is invalid you will need to do this:

var query;

 

for(var i = 0; i <excludedUserList.length; i++){

 

query += "sys_id!="+ excludedUserList[i] +"^"

 

}