If you’re a ServiceNow portal developer, chances are you’re fully aware of the portal widget ‘data’ object and all it has to offer. You may be surprised that portal widgets aren’t just for portal pages. In fact, portal widgets fit nicely into service catalog items.
Here’s a look at two new methods (along with the code for both) you can use to access server data in your portal-based service catalogs.
The first screenshot shows a catalog item macro variable type. The macro variable can hold a few different objects that can be represented on a catalog item, one of them being a Service Portal widget.
The widget is displayed in the second screenshot. Notice there’s a UI consisting of HTML (and Angular). Leveraging portal widgets is a great way to develop robust offerings that go beyond basic catalog design patterns. In this example, we have an input that allows the user to type anything they wish and display it on the very first form variable (Populated onClick from form buttons).
The user also has the ability to select from the ‘Populate w/User Data’ drop-down and populate this variable with the current user’s email, title, or username. Finally, the user can mouse over and select any role to populate the form variable with that role’s title.
- Input field and data population buttons that will populate item 3 (drop-down is ‘data’ object driven).
- Mouse-over menu click to populate item 3 (‘data’ object list).
- Populated through user text or ‘data’ object button items.
- Reference field populated onLoad through client script call to custom widget API through ‘data’ object.
- Reference field populated onLoad through traditional GlideAjax.
- Reference field populated onLoad directly from ‘data’ object, no client script. Direct from script included.
After the listed roles, we have three more catalog reference variables (sys_user table) that are pre-populated in three different ways with the current user. One variable is being populated by the same source that generated all the data above, while the other is being populated by a standard GlideAjax call.
Now, let’s look at other options for client scripting and server scripting.
Client Scripting (3 ways, same result)
Example #1: Populated from portal widget: using onLoad custom API call
Using the custom API generated from our portal widget, we can instantiate and call methods that are linked directly to the widget’s client script, which can be connected directly to the widget’s server-side scripting/’data’ object.
- onLoad we need to set the timeout to allow all the page assets to load.
- Functional instantiation. This function exists in the HTML of the widget and is available on page load.
- Associating our desired method and setting its value to our variable.
While this method is used to perform something mundane in this example, it can be used to initiate a complex data push or pull. Additionally, you can perform conditional DOM manipulations with this method. This example has been understated to illustrate the concept.
Example #2: Populated from GlideAjax (this is provided for comparison purposes only)
This is your standard GlideAjax call being shown for comparison. Please see ServiceNow’s documentation if you would like to learn more about GlideAjax. You can leverage this method to return one or multiple values through an asynchronous callback function. Please note: You must have an independent client-callable script include to accompany this.
Example #3: Populated from portal widget using: $scope.page.g_form
This code is used in the widget’s Client Controller only. No other code is necessary anywhere
- Set a familiar named object to the scope’s actual ‘g_form’ object.
- Consume the ‘data’ object directly from the script include called from the widget’s server scripting
- Alternatively, you could skip the script include and place all scripting here
- Using the script include offers obvious centralized global access
Example #1 and Example #3: Both are using a variation that calls the same data from the same script include. What you’re missing in this formula is the widget code. Here’s the script include:
Notice the function does not include a ‘return.’ The ‘data’ object is exposed when the widget loads.
Example #2: GlideAjax prototype (this is provided for comparison purposes only)
So as not to downplay GlideAjax, you can absolutely create and return JSON objects and reach out to non-callable functions.
Portal Widget (Examples #1 and #3 will use this)
Keep in mind that the ‘data’ object is exposed to the widget on page load through the server script of the widget (scope). The widget server script is the first portion of the widget to load. Essentially, an API can be developed through a widget that can be used for multiple catalog items by simply including it in the Macro.
Select widget code snippets
The widget HTML allows you to create the widget UI and it also allows you to create functions and methods to call Angular functions that are linked to the server scripting (data object).
In Example #1, we made a call to a function from a catalog onLoad client script
This script was calling a function from the widget’s HTML scripting
Notice that this function’s ‘userSysID’ method is returning an Angular object that is calling one of the widget’s client controller functions (c.userSysID()). This can be a more difficult way of performing the particular action since the ‘data’ object is already exposed. This is included to demonstrate a method to actuate widget functions from a catalog client script.
The widget’s client controller function is returning our ‘data’ object for Example #1
The widget’s client controller function is returning our ‘data’ object for Example #3
For Example #3, there is no catalog client script, this is all you need from the widget client controller
The ‘data’ object is being populated from the script include through the widget’s server script. This last step exposes all the data within any script include function. This applies to both Example #1 and #3.
Full widget code: HTML
Full widget code: CSS
Full widget code: Client Controller
Full widget code: Server Script
→Pro Tip: If you’ve ever found yourself needing to perform a particular g_form action 20 or more times in a single script, you could easily create a function call and pass a comma-delimited string parameter of variable names to the widget client script. At the client script, you can iterate through the list and automatically generate virtual g_form calls for each catalog variable you listed. Here’s an example of a script that is performing 3 g_form functions on as many catalog variable names placed in the ‘list’ parameter. In the catalog, this would be a three line call for about five variables instead of 15 lines:
Bottom line: The widget technique doesn’t replace GlideAjax. Outside of the portal, this method has no merit. If you have a requirement to develop catalog offerings that will be viewed from the native UI, GlideAjax is what you will need to use. If you have a requirement to develop catalog offerings that will only be viewed from the Service Portal, this method is an option.
Interested in learning more about how to simplify access to your Service Catalog data in ServiceNow? Please contact us at firstname.lastname@example.org.
*Author’s note: Code provided in this article was written in a manner to provide configuration options and do not always reflect my personal choice of techniques. For example, in the ‘_getRoles’ function, I purposely provided an extended code version to demonstrate how extensive you can be when populating the data object.