The Now Platform® Washington DC release is live. Watch now!

Help
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Jake Gillespie
Kilo Guru

In my previous post on Coding Best Practices, we reviewed some Best Practice tips for scripting in general. The ServiceNow platform allows Administrators to enhance the standard functionality by adding scripting to various system components. These components can be separated into two categories: Client-side and Server-side. Now, we'll review some of the Best Practices for Client-side Scripting in ServiceNow.

For reference, Client-side scripts are loaded into a user's Web Browser when a page is loaded. Some of these scripts execute automatically after the form is loaded (e.g. onLoad), while others only execute based on a user interaction (e.g. onChange or onSubmit). These scripts are written in JavaScript and can easily fail if not implemented correctly. If this occurs, the page will most likely not function as intended, resulting in corrupted values and a bad user experience. To avoid this, here are my Best Practice recommendations:

Avoid global Client Scripts

Client Scripts configured on the Global Table will be loaded on every single table form in the system, regardless of whether any of the code is actually needed. This can seriously impact system performance and therefore should be avoided. Client Scripts should be configured to load/execute on specific tables only. Consideration should also be given to whether the script should be inherited by any extended tables, and which views it should apply to. If functions are needed to be loaded on every form, a UI Script could be created.

Avoid using DOM (manipulating elements via the Document Object Model)

This is a bold statement I know, but it really is just the tip of an iceberg full of potential issues. So why is DOM manipulation such an issue? Well let's take a simple example. Let's say you want to hide a field element. You could inspect the HTML source and identify which element represents the field. Once you know the id value, you could call a standard JavaScript function called document.getElementById() to return the element as a JavaScript Object. Then, you could dot-walk to its style.display property and update its value ("none" for hide, "block" or "inline" for show etc). This would be perfectly fine if the HTML never changed. However, the HTML in ServiceNow's table forms is maintained by ServiceNow, and could (and likely will) change with future releases. If the id value changed, our scenario would fail. Some DOM calls go further than just targeting a specific element by id and could return elements based on their position in the form. Once again, if this position changes, the code would likely fail. Because of this, ServiceNow recommends avoid using DOM where possible, and if you do need to access one of the out-of-box elements, use the GlideForm (g_form) API instead (e.g. use the getElement() function to return the applicable element as an Object). Because ServiceNow maintain both the HTML structure and the GlideForm API, we can rely on their code to return the correct HTML element each time. Another tip is to always check that an Object was returned by the getElement() or document.getElementById() functions, before proceeding to dot-walk to other properties down the tree. This is important because if the element cannot be found, the value returned will be null. If you attempt to dot-walk and access non-existent properties or functions on a null object, the JavaScript processor will fail and produce an error, and in some cases prevent further processing. This usually causes the page to not function as intended, and creates a poor user experience. Even UI Policies can stop working if a page encounters a JavaScript error during the form load.

Use UI Policies instead of Client Scripts

Often times, we need to make a field read only, mandatory or hidden. For these cases, it is Best Practice to use UI Policies to perform these actions instead of calling functions from the GlideForm (g_form) API in Client Scripts. UI Policies also have the added advantage of being triggered by multiple conditions (e.g. field value changes), instead of just a single field value change (like an onChange Client Script). Additionally, UI Policies can be executed in a specific order, as well as execute further JavaScript functions if required.

Use Asynchronous calls via getReference() or GlideAjax

In my earlier post on Client-Server Communication, I discussed examples of using getReference() and GlideAjax to request data from the Server. Both of these examples used Asynchronous AJAX calls because that is the ServiceNow Best Practice. Using Asynchronous AJAX calls (e.g. using Callback functions) will avoid freezing the web browser while the data transfer occurs, and results in a much nicer user experience.

Use g_scratchpad to minimise server calls

Often, we need to use data in our Client Scripts, which is available on the Server, but not readily available on the Client. If these values are known when the form is loaded, they can be retrieved by a Display Business Rule, and made available to Client Scripts by storing them on a global JavaScript Object called g_scratchpad. Such examples include System Properties or field values from Database records. By first storing them on the g_scratchpad object when the form is loaded, it avoids the need to use an AJAX call to request and receive the required data.

Set the Display Value as well as the Value on Reference fields

When setting the value of a Reference field via script, we need to use (at minimum) the sys_id value of the record we want to select. When this happens, ServiceNow will automatically make a Synchronous AJAX call to the Server to determine the Display Value for the record we've selected, and then display this value on the form. As per my previous points on Client-Server communication and Asynchronous vs Synchronous AJAX calls, it is Best Practice to avoid Synchronous calls altogether, and to minimise server calls in general. With this in mind, the Best Practice when setting a value into a Reference field is to also set the Display Value at the same time, as this will prevent the additional Synchronous call to the Server. This can be achieved by adding an additional argument to the setValue() function. For example:

find_real_file.png

Never use GlideRecord in Client Scripts

Although the GlideRecord Class is available on the Client-side, ServiceNow recommends using GlideAjax instead. First of all, unlike the Server-side equivalent, the Client-side version of the GlideRecord Class will not provide the same functionality (e.g. no dot-walking and associated function calls). Second, whenever the next() or get() functions are called, a Synchronous AJAX call will be made to the Server and this will momentarily freeze the web browser until the data is returned. Using the Client-side GlideRecord Class is actually very similar to using getReference() with no Callback function, and as discussed in my earlier post on Client-Server Communication, the data returned will contain every field value for the selected record. In the case of records with many fields (or large field lengths) this will take longer to return, and could therefore cause performance issues and create a poor user experience.

In this article we've covered some of the principles behind Client Script Best Practices in ServiceNow. In my next article, we'll discuss Server Side Scripting Best Practices and how they apply specifically to ServiceNow. For further information on the topics covered in this article, please see the following pages on the ServiceNow Wiki:

NOTE: MY POSTINGS REFLECT MY OWN VIEWS AND DO NOT NECESSARILY REPRESENT THE VIEWS OF MY EMPLOYER.