Join the #BuildWithBuildAgent Challenge! Get recognized, earn exclusive swag, and inspire the ServiceNow Community with what you can build using Build Agent.  Join the Challenge.

dot-walking request table to requested item for ui action button

EnricoManalo23
Tera Contributor

I'm trying to make a cancel button that relies on the requested item 'item' field in the request form, currently can't seem to make it exclusive or dependent on the request  form since the request form is mapped to the request table.

12 REPLIES 12

Ankur Bawiskar
Tera Patron
Tera Patron

@EnricoManalo23 

You can't access RITM field when UI action is on REQ table

1 Request can have multiple RITMs?

how will you handle this then?

If you are sure always 1 REQ will have 1 RITM then you can use script include and call that from UI action condition

new RequestUtils().canCancelRequest(current)

var RequestUtils = Class.create();
RequestUtils.prototype = {
    initialize: function() {},

    canCancelRequest: function(current) {
        var ritm = new GlideRecord('sc_req_item');
        ritm.addQuery('request', current.sys_id);
        ritm.addQuery('car_item.name', 'Your Item Name Here');
        ritm.query();
        return ritm.hasNext();
    },

    type: 'RequestUtils'
};

AnkurBawiskar_1-1761132851242.png

 

💡 If my response helped, please mark it as correct and close the thread 🔒— this helps future readers find the solution faster! 🙏

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

@EnricoManalo23 

Hope you are doing good.

Did my reply answer your question?

💡 If my response helped, please mark it as correct and close the thread 🔒— this helps future readers find the solution faster! 🙏

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

MaxMixali
Giga Guru

ServiceNow Solution: Cancel Button Dependent on Requested Item (Request vs Requested Item)

-------------------------------------------------
Problem
-------------------------------------------------
The Request form (sc_request) does not have the Catalog Item (cat_item) field.
The Catalog Item exists on Requested Item (sc_req_item).
A Request can contain multiple Requested Items (RITMs), so the Cancel button cannot depend directly on a single item field from the Request.

-------------------------------------------------
Option A – Place Cancel Button on Requested Item (Recommended)
-------------------------------------------------
UI Action (server-side) on table sc_req_item
Condition (Display):
current.isValidRecord() &&
current.state != 'closed_complete' &&
current.state != 'closed_incomplete' &&
current.state != 'cancelled' &&
gs.hasRole('itil');

Script:
(function cancelRITM() {
if (typeof workflow != 'undefined' && workflow.cancel) {
workflow.cancel(current);
}
current.setValue('state', 'cancelled');
current.setValue('approval', 'cancelled');
current.update();

gs.addInfoMessage('Requested Item cancelled.');
action.setRedirectURL(current);
})();

This button is item-dependent and simple to manage.

-------------------------------------------------
Option B – Keep Button on Request (sc_request) and Evaluate Child RITMs
-------------------------------------------------
B1) Single Eligible RITM Logic

Condition:
(function showOnSingleEligibleRITM() {
var ritm = new GlideRecord('sc_req_item');
ritm.addQuery('request', current.sys_id);
ritm.addQuery('state', '!=', 'closed_complete');
ritm.addQuery('state', '!=', 'closed_incomplete');
ritm.addQuery('state', '!=', 'cancelled');
ritm.query();

var count = 0, only;
while (ritm.next()) { count++; only = ritm.copy(); }
if (count != 1) return false;

// Example: check item sys_id
// return (only.cat_item == 'ITEM_SYS_ID');
return gs.hasRole('itil');
})();

Script:
(function cancelSingleChild() {
var ritm = new GlideRecord('sc_req_item');
ritm.addQuery('request', current.sys_id);
ritm.addQuery('state', '!=', 'closed_complete');
ritm.addQuery('state', '!=', 'closed_incomplete');
ritm.addQuery('state', '!=', 'cancelled');
ritm.query();
if (ritm.next()) {
cancelRITM(ritm);
}
action.setRedirectURL(current);

function cancelRITM(r) {
if (typeof workflow != 'undefined' && workflow.cancel) workflow.cancel(r);
r.setValue('state', 'cancelled');
r.setValue('approval', 'cancelled');
r.update();
}
})();

B2) Cancel All Eligible RITMs

Condition: at least one cancellable RITM.

Script:
(function cancelAllChildren() {
var ritm = new GlideRecord('sc_req_item');
ritm.addQuery('request', current.sys_id);
ritm.addQuery('state', '!=', 'closed_complete');
ritm.addQuery('state', '!=', 'closed_incomplete');
ritm.addQuery('state', '!=', 'cancelled');
ritm.query();
var cancelled = 0;
while (ritm.next()) {
if (isItemCancellable(ritm)) {
cancelRITM(ritm); cancelled++;
}
}
gs.addInfoMessage('Cancelled ' + cancelled + ' Requested Item(s).');
action.setRedirectURL(current);

function isItemCancellable(r) {
// Put item-specific condition here
// return (r.cat_item == 'ITEM_SYS_ID');
return true;
}
function cancelRITM(r) {
if (typeof workflow != 'undefined' && workflow.cancel) workflow.cancel(r);
r.setValue('state', 'cancelled');
r.setValue('approval', 'cancelled');
r.update();
}
})();

-------------------------------------------------
Option C – Derive Primary Item on Request
-------------------------------------------------
Add a Business Rule on sc_req_item to set a field u_primary_cat_item on sc_request
(if there’s a single RITM or a business-defined “primary” one).
Then, in your Request UI Action condition, reference current.u_primary_cat_item.

-------------------------------------------------
Service Portal and Workspace Notes
-------------------------------------------------
In Service Portal: extend the request page server script to check child RITMs before exposing the cancel button.
In Workspace: use a Record UI Action or a UI Builder button calling a Scripted REST API with the same logic.

-------------------------------------------------
Summary
-------------------------------------------------
- sc_request has no item field; sc_req_item does.
- Place cancel logic on RITM if possible (Option A).
- For Request-level actions, inspect child RITMs (Option B) or derive item data (Option C).
- Choose the simplest approach matching your business need.

Key takeaway:
You cannot directly depend on the Item from the Request form because the item lives on its child RITMs. Query them or derive a field on Request to drive conditional logic.