Approval Widget Cancel button change status and add comment to work note
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
ā05-12-2025 11:33 AM
I'm currently working on extending a custom approval widget in ServiceNow to include a "Cancel" button alongside the existing "Approve" and "Reject" options.
The goal is:
When a user selects Cancel, a comment is required.
Upon submission, the widget should:
Update the record_status field on custom table (on both the approval and related custom task record) to 'cancelled'.
Add the user's comment as a work note on the related custom task record (e.g., x_g_dh5_ccht_ccht_task).
The reject button is changing the status to the record but not adding the comment once submitted.
HTML:<div class="panel panel-{{::c.options.color}} b"><div class="panel-heading"><h4 class="panel-title" ng-if="c.data.state == 'requested'">${This {{c.data.label}} requires your approval}</h4><h4 class="panel-title" ng-if="c.data.state == 'approved'">${Approved} <sn-time-ago timestamp="::c.data.sys_updated_on" /></h4><h4 class="panel-title" ng-if="c.data.state == 'rejected'">${Rejected} <sn-time-ago timestamp="::c.data.sys_updated_on" /></h4><h4 class="panel-title" ng-if="c.data.state == 'cancelled'">${Cancelled} <sn-time-ago timestamp="::c.data.sys_updated_on" /></h4></div><div class="panel-body"><form ng-submit="$event.preventDefault()" class="form-horizontal"><div ng-if="c.data.fields.length > 0"><div ng-repeat="field in c.data.fields" class="m-b-xs" ng-if="field.value"><label class="m-n">{{field.label}}</label><span ng-switch="field.type"><div ng-switch-when="glide_date_time" title="{{field.display_value}}"><sn-time-ago timestamp="::field.value" /></div><div ng-switch-default >{{field.display_value}}</div></span></div></div><div ng-if="c.data.state == 'requested'" class="question"><button type="button" name="approve" class="btn btn-success btn-question" ng-click="c.action('approved')">${Approve}</button><div class="spacer"></div><button type="button" class="btn btn-default btn-question" ng-click="c.openModal('rejected')">${Reject}</button><div style="height: 20px;"></div><button type="button" class="btn btn-default btn-question" ng-click="c.openModal('cancelled')">${Cancel Request}</button></div></form></div></div><!--Setting Window for Comments JWD --><script type="text/ng-template" id="modalTemplate"><div class="panel panel-default"><div class="panel-body"><div class="form-group"><label>{{ c.modalAction === 'cancelled' ? 'Justification for Cancelling Request' : 'Comments required when rejecting' }}</label><input class="form-control" ng-model="c.data.comments" required /></div><div class="form-group"><buttonng-disabled="!c.data.comments"class="btn btn-primary btn-sm"ng-click="c.action(c.modalAction); c.closeModal();">${Submit}</button></div><div class="panel-footer text-right"><button class="btn btn-default" ng-click="c.closeModal()">Cancel</button></div></div></div></script>
Client Script:function ($scope, $uibModal) {var c = this;c.data.comments = "";c.action = function(state) {c.data.op = state;c.data.state = state;c.server.update();}//Opens the pop-up for comments. JWDc.openModal = function(actionType) {c.modalAction = actionType; // either 'cancelled' or 'rejected'c.modalInstance = $uibModal.open({templateUrl: 'modalTemplate',scope: $scope});}c.closeModal = function() {c.modalInstance.close();}}
Server Script:var gr = $sp.getRecord();
if (input && input.op && gr) {
gs.info("[WIDGET] Received comments: " + input.comments);
gs.info("[WIDGET] Updating approval record: " + gr.getTableName() + " | " + gr.getUniqueValue());
gr.comments = input.comments;
gr.state = input.op;
gr.update();// Update related task (x_g_dh5_ccht_ccht_task)
var targetRecord = getRecordBeingApproved(gr);
gs.info("[WIDGET] Related task record: " + (targetRecord ? targetRecord.getUniqueValue() : 'No related record'));if (targetRecord && targetRecord.isValidRecord()) {
gs.info("[WIDGET] Updating related task record: " + targetRecord.getTableName() + " | " + targetRecord.getUniqueValue());
targetRecord.setValue('state', input.op);// Check if work_notes field is valid and update it
if (targetRecord.isValidField('work_notes')) {
targetRecord.setValue('work_notes', input.comments); // Set comments in work_notes
} else {
gs.info("[WIDGET] work_notes field is not valid on related task record.");
}targetRecord.update();
} else {
gs.info("[WIDGET] No valid related task record found or not accessible.");
}
}var fields = $sp.getFields(gr, 'state,sys_created_on');
if (gr) {
if (gr.sys_mod_count > 0)
fields.push($sp.getField(gr, 'sys_updated_on'));data.fields = fields;
data.state = gr.state.toString();
data.sys_updated_on = gr.sys_updated_on.toString();
data.sys_id = gr.getUniqueValue();
data.table = gr.getTableName();var related = getRecordBeingApproved(gr);
if (related && related.isValidRecord()) {
data.label = related.getLabel();
} else {
data.label = gr.getLabel();
}
}function getRecordBeingApproved(gr) {
if (!gr.sysapproval.nil()) return gr.sysapproval.getRefRecord();
return gr.document_id.getRefRecord();
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
ā05-12-2025 12:18 PM - edited ā05-12-2025 12:19 PM
try
gr.comments.setJournalEntry(input.comments.toString());
Please accept my solution if it works for you and thumps up.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
ā05-13-2025 07:47 AM
This seems to only work within global applications
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
ā05-13-2025 11:50 AM
Then gr.comments = input.comments.toString(); should work fine for scoped apps.