Catalog item

vishaldhama
Tera Contributor

Hi Team,

I am working on a Catalog Item that includes a Variable Set containing a variable named "Software Model".

Requirement:
I want to filter or set the value of the "Software Model" variable dynamically based on certain conditions.

What I have tried:
I attempted to use a Client Script and reference qualifier to control the values, but the behavior is not consistent.

Issue:
The variable works as expected in the backend (Maintain Items view), but it is not working properly in the Service Portal.

Expected Result:
The "Software Model" variable should display or set the correct values dynamically in both backend and Service Portal.

Actual Result:
It is either not showing values or not setting correctly in the Service Portal.

Additional Info:
- Variable Type: Reference
- Table: alm_entitlement (or relevant table)
- Used inside: Variable Set
- Script Type: Client Script / Reference Qualifier

Can someone please suggest the correct approach to achieve this?

Thanks!

1 REPLY 1

Naveen20
ServiceNow Employee

 

The Service Portal uses a different rendering engine (Angular-based widget: sc_cat_item) than the backend (standard Jelly/Glide form renderer). Several things behave differently: client-side GlideRecord calls are restricted, g_form API support is a subset of what's available in the backend, and reference qualifiers that rely on client-callable Script Includes need explicit ACL and scope access.

Step-by-step approach to fix this:

1. Use Catalog Client Scripts (not regular Client Scripts)

Make sure your script is a Catalog Client Script (catalog_script_client), not a standard Client Script. On the Catalog Client Script record, confirm the "Applies to" field is set to run on both Desktop and Service Portal. There's a "UI Type" field — set it to Both (or "Mobile / Service Portal" if you only care about portal). If it's set to "Desktop" only, the Service Portal will ignore it entirely.

2. Use an encoded query-based Reference Qualifier (avoid scripted if possible)

Scripted reference qualifiers using javascript: work in the backend but can be unreliable in Service Portal. The most reliable approach is to use a dynamic but encoded-query-based reference qualifier on the variable definition itself. For example, instead of:

javascript: new MyUtils().getQualifier();

Try a straightforward encoded query string directly on the variable's Reference Qualifier field:

active=true^model_category=software

If you absolutely need dynamic filtering based on another variable's value, use the ^ operator with variable substitution syntax. ServiceNow supports javascript:current.variables.variable_name in some contexts, but for Service Portal, the more reliable pattern is to use a Catalog Client Script (onChange) that sets a reference qualifier dynamically via g_form.getControl() — except getControl() doesn't exist in Service Portal either. So the recommended approach is #3 below.

3. The recommended pattern for dynamic filtering in Service Portal

Use a combination of a Catalog Client Script and a client-callable Script Include with a reference qualifier that calls it:

On the variable's Reference Qualifier field, set:

javascript: new global.SoftwareModelUtils().getRefQual(current);

Then create a Script Include (SoftwareModelUtils😞

var SoftwareModelUtils = Class.create();
SoftwareModelUtils.prototype = Object.extendsObject(AbstractAjaxProcessor, {

    // Called from the Reference Qualifier
    getRefQual: function(current) {
        var query = 'active=true';
        // Add your conditional logic here
        // e.g., filter by a category variable value
        var category = current.variables.category;
        if (category) {
            query += '^model_category=' + category;
        }
        return query;
    },

    // Client-callable method for Service Portal
    getModels: function() {
        var category = this.getParameter('sysparm_category');
        var query = 'active=true';
        if (category) {
            query += '^model_category=' + category;
        }
        return query;
    },

    type: 'SoftwareModelUtils'
});

Make sure the Script Include has Client callable checked and is in the global scope (or the same scope as your catalog item, with proper cross-scope access).

Then in your Catalog Client Script (onChange of the dependent variable like "Category"), refresh the reference field:

function onChange(control, oldValue, newValue, isLoading) {
    if (isLoading) return;

    // Clear current value
    g_form.clearValue('software_model');

    // This forces the reference qualifier to re-evaluate
    // when the user opens the dropdown
}

The key insight is that in Service Portal, just clearing the value and letting the reference qualifier re-evaluate on the server side (when the user next interacts with the lookup) is more reliable than trying to manipulate the field client-side.

4. If you need to SET the value programmatically

Setting a reference field value in Service Portal requires both the sys_id and the display value. Use setValue with both arguments:

g_form.setValue('software_model', sysId, displayValue);

If you only pass the sys_id, Service Portal may show the sys_id as text or show nothing. You can fetch the display value via a GlideAjax call to a client-callable Script Include:

function onChange(control, oldValue, newValue, isLoading) {
    if (isLoading) return;

    var ga = new GlideAjax('global.SoftwareModelUtils');
    ga.addParam('sysparm_name', 'getDefaultModel');
    ga.addParam('sysparm_category', newValue);
    ga.getXMLAnswer(function(answer) {
        var result = JSON.parse(answer);
        if (result.sys_id) {
            g_form.setValue('software_model', result.sys_id, result.display_value);
        }
    });
}