A recent project I was working on had me crawling through a tangled web of various Client Scripts and UI Policies. The more time I spent poring over the code, the more confused I became about which record should be setting which fields on the form I was looking at. Finally, I decided to do a little experiment to test whether Client Scripts or UI Policies take precedence. I figured it would also be good to go over the best practice for when to use Client Scripts vs UI Policies.
In this article, we’ll start by going through my experiment and the results. After that, we’ll go over a few gotchas and then what ServiceNow considers “best practice”. My hope is that this article will help you avoid the same confusion and frustration that I faced.
UI Policies allow you to dynamically change the behavior of a form. Each UI Policy consists of UI Policy Actions and/or client-side scripts. UI Policy Actions let you handle whether or not a specific field should be mandatory, visible, read only, or cleared. For this experiment, I’ve created the following “Secret Agents” form and corresponding UI Policy. Here I have a “Secret Identity” field that is only shown if they select the “Show Secret Identity” checkbox.
Client Scripts allow you to run client-side code on a form when it loads, when it’s edited, or when it’s submitted. Take a look at the following Client Script. Both the “Show Secret Identity” and “Secret Identity” fields are hidden. After all, NO ONE should know an agent’s secret identity!
As you have hopefully noticed, the UI Policy and Client Script are conflicting. The Client Script is attempting to hide the “Secret Identity” field whenever a user goes to an existing Secret Agent record. The UI Policy, on the other hand, is showing the “Secret Identity” field whenever the “Show Secret Identity” field is checked. So what happens if the “Show Secret Identity” field is checked and we open an existing Secret Agent record? Will the “Secret Identity” field be visible or hidden?
If we open one of the Secret Agent records that had “Show Secret Identity” set to true, we can see that the “Secret Identity” field shows up. That means that Client Scripts run first and UI Policies run last. Because UI Policies run last, they take precedence on the form behavior. Note that the “Show Secret Identity” field is still hidden. That is because the UI Policy did not set that field behavior and therefore did not override what was defined in the Client Script. Only the “Secret Identity” field visibility was set in the UI Policy.
To verify our claim that the UI Policy wins, let’s try switching the logic so that the UI Policy is the one hiding both the “Show Secret Identity” and “Secret Identity” fields and the Client Script is the one showing the “Secret Identity” field if the “Show Secret Identity” checkbox is set.
If we reload our Secret Agent form, we see that both fields are hidden. This aligns with the assertion that UI Policies run last and therefore take precedence.
Using Both Client Scripts and UI Policies
For starters, having a Client Script and UI Policy on the same form can be super confusing. Hopefully that was apparent as we went through our experiment. If you are modifying the same field or section in both the Client Script and UI Policy, you can end up hiding/exposing fields you didn’t mean to. The UI Policy will always take precedence (as we discovered in this post), so if you’re scratching your head over a Client Script that isn’t modifying the form behavior as you expect, be sure to check the UI Policies to see if there are any conflicts. We’ll go over best practices in the next section to help avoid that situation.
g_form.setVisible() vs g_form.setDisplay()
Another gotcha that I have run into in the past (even as I was writing this post) is that g_form.setVisible() is NOT the same as g_form.setDisplay(). g_form.setVisible() hides the field but it leaves the space that the field was in. g_form.setDisplay() removes the field and the space that it was in so that other fields move up and take its place. I would stay clear of g_form.setVisible() unless you really need it. As seen in the image below, UI Policy Actions use g_form.setDisplay() behind the scenes to set field visibility. So should you 😉
Mandatory Fields not Hiding
The last gotcha that I’ll cover in this article is that mandatory fields cannot be hidden unless they are first marked as non-mandatory. So if you’re going to hide a mandatory field, make sure to mark it as non-mandatory first, otherwise the field will stay on the form.
As mentioned in the the first gotcha, it can get really confusing really fast if you have both UI Policies and Client Scripts running on the same form. Best practice is to only use one or the other. If you can get away with just using UI Policies, that is the best route to take. According to the UI Policy documentation, “You can also use client scripts to perform all of these actions, but for faster load times use UI policies when possible.” If, however, you start getting into more complicated form behavior and neither UI Policy Actions nor UI Policy scripts are working for your use-case, move your UI Policy functionality over to Client Scripts. When possible avoid having both UI Policies and Client Scripts on the same form. Breaking that best practice is how I ran into the issues that inspired this article.
Hopefully I’ve helped clear up any confusion you might have about Client Scripts vs. UI Policies. In general, it’s best to use UI Policies, but both UI Policies and Client Scripts have their place. ServiceNow has done a fantastic job documenting these two client-side options, so when it doubt, refer to the docs!