Catalog item
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
yesterday
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!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
22m ago
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);
}
});
}
