M
ost Service-now administrators and consultants know how to configure and use UI Actions. UI Actions are UI elements that can show up on a form or a list as a button, link, or context menu. When these UI elements are clicked they execute some JavaScript. Most of the time UI Actions are used to perform some server-side update to a record or records. In other cases, you can use the ‘Client’ checkbox on the UI Action record to execute some client-side JavaScript (including checking for mandatory fields).
But what if you need to do both? The classic case is when you want to click a button to make an update to a record, but only if the user has provided the correct input first. An example would be a ‘Reopen Incident’ button that changes the state on an incident record from ‘Resolved’ to ‘Active’. Usually you want to require the user to provide some sort of comment or additional information explaining why they are reopening the ticket. The problem is that you don’t always want the ‘Comments’ field to be mandatory so the validation needs to happen at the time the ‘Reopen Incident’ button gets clicked. Validation of mandatory fields needs to happen client-side but the update to your record needs to happen server-side. How can you accomplish both of these things with a single UI Action? This article shows you how.

The basic format for using a Client Script and Business Rule in the same UI Action looks something like this…
Name: -Button Name-
Action name: -button_action_name- (Should be unique per button on form and gets called from the UI Action script)
Client: True (MUST be checked)
Form button/Form Context Menu/Form Link: (UI Action must be one of these ‘Form’ types)
Onclick: -runClientCode();- (Points to the function in your script that should be run when the UI Action gets clicked)
Script:
function runClientCode(){
if(<CONDITION_TO_VALIDATE> == false){
return false; //Abort submission
}
//Call the UI Action and skip the 'onclick' function
gsftSubmit(null, g_form.getFormElement(), '<button_action_name>'); //MUST call the 'Action name' set in this UI Action
}
//Code that runs without 'onclick'
//Ensure call to server-side function with no browser errors
if(typeof window == 'undefined')
runBusRuleCode();
//Server-side function
function runBusRuleCode(){
current.<field_name> = <value>;
current.update();
gs.addInfoMessage('You did it!');
action.setRedirectURL(current);
}
So why does this work? I had to go to a Service-now developer to find out. The reason is that UI Actions can run scripts at two different times. The first time is when the UI Action gets clicked. When you define a ‘Client’ UI Action you also give that UI Action the name of a function in your ‘Script’ field to execute. This function has to be called explicitly (through the ‘onclick’ event) or it doesn’t run at all.
The second time is on the way to the server. This is how any UI Action without the ‘Client’ checkbox selected gets run. On the way to the server the entire UI Action script gets executed regardless of whether or not the ‘Client’ checkbox is checked. What this means is that any script you include in your UI Action that isn’t enclosed in a function will be run on the way to the server. The script above takes advantage of this fact by making a specific call to the ‘Client’ function, performing client-side validation, and then the UI Action calls itself if the client-side validation passes.
When the UI Action calls itself it bypasses the ‘onclick’ function because the button didn’t get clicked the second time. So the script continues to the first point where there is something to execute. At that point you can call your Server-side function! The only thing you need to be careful of is that you only call the Server-side function if the script isn’t running in the client anymore. That’s what the check in the middle does…and eliminates any browser errors saying that ‘current’ (or any other Server-side function or object) isn’t defined.
Here is a solution I’ve used in the past to give users the ability to reopen an incident record. The solution uses a UI Action button to check if the ‘Comments’ field has been filled in (this is the ‘Client-side’ portion). If the validation passes, then the incident record gets updated.
Name: Reopen Incident
Action name: reopen_incident
Client: True
Form button: True
Onclick: reopen();
Condition: current.state == 6
Script:
function reopen(){
if(g_form.getValue('comments') == ''){
//Remove any existing field message, set comments mandatory, and show a new field message
g_form.hideFieldMsg('comments');
g_form.setMandatory('comments', true);
g_form.showFieldMsg('comments','Comments are mandatory when reopening an Incident.','error');
return false; //Abort submission
}
//Call the UI Action and skip the 'onclick' function
gsftSubmit(null, g_form.getFormElement(), 'reopen_incident'); //MUST call the 'Action name' set in this UI Action
}
//Code that runs without 'onclick'
//Ensure call to server-side function with no browser errors
if(typeof window == 'undefined')
serverReopen();
function serverReopen(){
//Set the 'State' to 'Active', update and reload the record
current.state = 2;
current.update();
gs.addInfoMessage('Incident ' + current.number + ' reopened.');
action.setRedirectURL(current);
}
Comments
Posted On
Aug 31, 2010Posted By
Richard HussIngenious – and somewhat simpler than the way the Incident Resolution best practice plugin does the same sort of thing to make close notes mandatory on resolution or closure. The (BP) Close Mandatory on Close or Resolve client script is quite dastardly.
Posted On
Aug 31, 2010Posted By
Ron MethiasAnother reason why I have stopped going to the official SN documentation sites and make the GURU my documentation site of choice. You come up with clever solutions that every admin could use.
This is really cool!
Posted On
Sep 08, 2010Posted By
Joe WattsSo cool, makes it so much easier/cleaner to do confirm() before executing server-side code. Definitely something I will use all the time, thanks!
Posted On
Sep 14, 2010Posted By
Dhanraj PWorking perfectly…. thnks a lot for sharing this knowledge !!
Posted On
Mar 07, 2011Posted By
ThakHi,
I got a little problem with that script. Indeed, it works perfectly with buttons in the bottom of the form.
But, my buttons in the title bar does not work. They launch the script client side but the ‘gsftSubmit’ action is inactive. Maybe because the button has no id (when selecting client for the UI Action, the action name is not associated to the id of the html button).
Have you experienced that before?
Regards,
Thak
Posted On
Mar 07, 2011Posted By
Mark StangerI haven’t seen the problem you describe before.
Posted On
Mar 13, 2011Posted By
ThakFor your information, I have solved my problem.
As I expected, the problem was not coming from the code of that post. The point was coming from the List V2 plugin.
I was using a embedded list in my form, and as that list was empty, it was raising the following error in my FF javascript console :
this.tableElementDOM.rows[0] is undefined.
And that error was in conflict with the gsftSubmit action, so that the form was not able to be submitted.
Thanks for your quick answer.
P.S : I raised that bug to SNC
Posted On
Mar 14, 2011Posted By
Mark StangerWow, that’s a strange one. Thanks for digging in and figuring it out.
Posted On
Mar 16, 2011Posted By
Jim CoyneCool, got it working with a confirmation before undertaking the actual action. I’m using gs.addInfoMessage do add an info/error message at the top of the screen to say the action was successful or not, but the client would prefer an alert window instead. Would that be possible?? Can’t see how – I tried adding an alert after the call to the server side code, but it actually pops up before the code is run.
Posted On
Mar 16, 2011Posted By
Mark StangerI don’t think that’s possible if you’re trying to add the message after the server-side code executes. You’ll need to use addInfoMessage for that final confirmation.
Posted On
Mar 16, 2011Posted By
Jim CoyneThat’s what I figured. I used HTML to change the message to be pretty obvious and it takes up quite a bit of room at the top of the screen. If the user does not see it, then there’s a problem.
Thanks
Posted On
Apr 04, 2011Posted By
John GilaspyI want to use this script, but I keep getting an error that g_form is undefined. Any ideas why?
gsftSubmit(null, g_form.getFormElement(), ”);
Posted On
Apr 04, 2011Posted By
Mark StangerThe error suggests that you’re trying to run the script in a place other than a regular form. You won’t be able to get it to work from a UI page or a list for example. If you can set up a test on demo and reproduce there I can take a look.
Posted On
Apr 04, 2011Posted By
John GilaspyIt works fine, once you close and reopen the browser. That was all it took.
Posted On
May 25, 2011Posted By
Abhiram BharadwajFantastic ! Too Good.Thanks a lot Mark !
Posted On
Jul 23, 2011Posted By
Dhanraj PoojariThanks Mark!!
Posted On
Aug 17, 2011Posted By
Russ HartHi Mark,
I’m trying to use this in conjunction with a dialog.render in the client side, before updating the record on the server side. The problem I’m having is that the gsftSubmit(null, g_form.getFormElement(), ‘cancel_request’); line is actioned as soon as the dialog box is rendered so the user doesn’t get the chance to fill in the dialog box. Is there a way I can make it wait for the OK button on the rendered dialog to be pressed before proceeding to the gsftSubmit ?
Posted On
Aug 17, 2011Posted By
Mark StangerI’m not sure about the specifics of your setup, but it sounds like you need to have a ‘return false;’ line in your client-side piece of the UI action so that the bottom form doesn’t submit.
Posted On
Aug 17, 2011Posted By
Russ HartThanks Mark – unfortunately then the script stops so the server side part is never executed. I need it to still execute the server side part of the UI Action but only after the OK button on the dialog form is pressed.