Blog 
Service Now Client Script override for the Post button behaviour on the journal field in incident module (via DOM manipulation)
Friday 17th January 2025
I've been working with the Service Now platform for the past few years now in a professional sense, and I recently started writing my own customisations for the platform, I've actually got a few tips and tricks to share in future articles, but not sure of my audience or the value of said tips, and I am also not 100% confident that my changes comply with best practice guidelines, but what does? I've just gotten used to managing instances that are far from OOBE.
I want to preference that this is my first article on the subject, and all the testing that was conducted was done in a personal developer instance (PDI), Prior to moving it over to a production instance.
I have done my best to measure performance impacts on my code, and that appears to be negligible, but your mileage may vary, so use what's offered here at your own risk and use best practises when developing your own customizations.
For a bit of background,
ServiceNow offers a plethora of APIs and configuration options, most of the UI elements and buttons available within the platform itself can be tweaked or changed to fit specified business rules, the abstraction that ServiceNow provides is both a double edged sword, sometimes it's relatively easy to go in and modify a record and other times there's a bit more work involved to get things to work the way you want it to work, that was what I discovered when working on this customization.
For the requirements,
In this instance when a record is deemed to have a child record attached, a dialogue is to be presented to the user before updating a given record or committing notes to the journal field, most if not all buttons can be overwritten to have different behaviour except this one in particular, that is, the post button, on a specific combined comments and work note field, to get around this limitation I used DOM manipulation. (I am working with the Xanadu release).
I am also open to feedback, so if you find anything wrong with this method or can offer a better solution, please let me know.
SN Utils is also a lifesaver when doing this kind of work and the VS Code Extensions are also very helpful.
Script includes
Added to: .service-now.com/sys_script_include.do
Name: CheckhasChildIncidents
API Name: global.CheckhasChildIncidents
Glide AJAX enabled: True
Accessible from: This application scope only
Script:
var CheckhasChildIncidents = Class.create(); CheckhasChildIncidents.prototype = Object.extendsObject(AbstractAjaxProcessor, { hasChildIncidents: function(current) { var ticketHasChildIncidents = 'false'; if (current == 'undefined' || current == null) {current = this.getParameter('sysparm_number');} var rec = new GlideRecord('incident'); if (!rec.get(current)) return 'bad rec'; var gr = new GlideAggregate('incident'); gr.addQuery('child_incidents', current); gr.addAggregate('COUNT'); gr.query(); var count = 0; if (gr.next()) { count = gr.getAggregate('COUNT'); } if (rec.child_incidents > 0) { ticketHasChildIncidents = 'true'; } else { ticketHasChildIncidents = 'false'; } return ticketHasChildIncidents; }, type: 'CheckhasChildIncidents' });
The Client Script
Added to .service-now.com/sys_script_client_list.do
Name: Custom Comments/Work Notes Post Button
Table: Incident
UI Type: All
Type: onload
Global: True
Isolate script: False
Note: New client-scripts are run in strict mode, with direct DOM access disabled. Access to jQuery, prototype and the window object are likewise disabled. To disable this on a per-script basis, configure this form and add the "Isolate script" field. To disable this feature for all new globally-scoped client-side scripts set the system property "glide.script.block.client.globals" to false.
Script:
function onLoad() { var newButton = document.createElement("button"); var number = g_form.getValue('number'); var ga = new GlideAjax('global.CheckhasChildIncidents'); ga.addParam('sysparm_name', 'hasChildIncidents'); ga.addParam('sysparm_number', number); ga.getXML(function(response) { hasChildIncidentsResult = response.responseXML.documentElement.getAttribute('answer'); if (hasChildIncidentsResult === 'true') { var oldButton = document.querySelector('button[type="button"][class="btn btn-default activity-submit"][ng-keypress="submitCheck($event)"][ng-click="postJournalEntryForCurrent($event)"]'); oldButtonId = document.createAttribute('id'); oldButton.setAttributeNode(oldButtonId); oldButton.setAttribute("id", "OriginalFormPostButton"); ngclick = document.createAttribute('ng-click'); ngkeypress = document.createAttribute('ng-keypress'); nghide = document.createAttribute('ng-hide'); btnclass = document.createAttribute('class'); btnclass = document.createAttribute('type'); newButton.innerText = "Custom Post Button"; newButton.setAttributeNode(ngclick); newButton.setAttributeNode(ngkeypress); newButton.setAttributeNode(nghide); newButton.setAttributeNode(btnclass); newButton.setAttribute("class", "btn btn-default"); newButton.setAttribute("type", "button"); newButton.setAttribute("ng-click", "postJournalEntryForCurrent($event)"); newButton.setAttribute("ng-keypress", "submitCheck($event)"); newButton.setAttribute("ng-hide", "!false && doesFormHasMandatoryJournalFields()"); newButton.addEventListener("click", doPrompt); oldButton.style.visibility='hidden'; oldButton.after(newButton); } }); function doPrompt() { var message = getMessage("This update will be send to all child records. Are you sure?"); var dialogClass = window.GlideModal ? GlideModal : GlideDialogWindow; var dialog = new dialogClass('glide_confirm_standard'); dialog.setTitle(new GwtMessage().getMessage('Incident has related records.')); dialog.setPreference('warning', true); dialog.setPreference('title', message); dialog.setPreference('onPromptComplete', confirm.bind(this)); dialog.setPreference('onPromptCancel', cancel.bind(this)); dialog.render(); } function confirm() { newButton.removeEventListener("click", doPrompt); newButton.remove(); document.getElementById("OriginalFormPostButton").style.visibility='visible'; document.getElementById("OriginalFormPostButton").click(); } function cancel() { return false; } }
Finally, here's a screenshot of it in action.
For the behaviour of the script I have the prompt only present once and revert back to the original button functionality once the user has confirmed that they wish to proceed with the update.
Home | Blog Index | RSS

