Developing on ServiceNow's Service Portal can be tricky sometimes, especially if you are new to web development or new to AngularJS. This article attempts to make your job just a little bit easier by setting out a standard set of Service Portal Widget debugging techniques and is intended both for informational and training purposes. The techniques range in complexity from simply logging to the console to pulling the strings of your widget from the JavaScript console like a puppet master! In most situations, an understanding of the Basic Techniques section will suffice. For more complicated scenarios, a firm grasp of the Advanced Techniques may be required. The techniques in this article are a compilation of techniques gathered from currently available ServiceNow resources and new techniques which are documented here for the first time.
If you are completely new to Service Portal and are starting from scratch, you may want to have a look at these resources below before you start running the examples from this article.
AngularJS Tutorial w3schools.com
Service Portal fundamentals: AngularJS scopes
All examples in this article are run on a widget called "Global Objects Demo Widget". To run the examples in the article you will need to see section Running the Examples at the end of the article to get setup.
The console.log() function will log data to the JavaScript console in the browser. This technique will work in the Client Script of the widget and also in the Server Script. The fact that it works in the Service Script as well is a great advantage! I can't think of anywhere else in the ServiceNow platform where you can log to the JavaScript console from server-side JavaScript.
If you look at line 3 and line 16 of the Server Script of the Global Objects Demo Widget, you'll notice that the "input" and "data" objects are logged to the console.
Open the JavaScript console in Chrome developer tools. Refresh the preview pane and you'll notice the following result in the console:
The input object is undefined and the data object is printed to the console.
The debugger function can be used in the Client Script of the widget but not the Server Script. Adding the debugger function is like inserting a break point into your code allowing you to step through the code line by line.
In the Client Script of the widget, add the code debugger; at line 23.
Open Chrome Developer Tools. Save the widget and refresh the preview pane. Press the server.get({collectionName: "presidents"}) button. The JavaScript execution will stop at the word debugger. To see the "response" object contents, hover your mouse over the word "response" in line 14 of the code in devtools.
To step into the next line in the code use the down arrow button. To allow the JavaScript execution to proceed without stopping, press the "Resume script execution" button.
Hold down the control key and right-click on the widget. Choose "Log to console: $scope.data" or "Log to console: $scope". The only difference is whether you want to log the entire scope object to the console or only the data property of the scope object.
Navigate the to the following URL: https://.service-now.com/sp?id=demo_widget_example
Hold down the control key and right-click on the widget. Choose "Log to console $scope.data". Open Chrome Developer Tools and expand the object dumped to the console and verify that the value of $scope.data.prop1 is "Apple".
These advanced debugging techniques are not only cool but can be highly affective when troubleshooting on a production instance where it's not possible to make any changes. All the techniques below are run through Chrome Developer Tools.
You can think of this technique as an analogy to a puppet show. The puppeteer activates and manipulates the puppets (widgets) with a set of strings. In this case we're creating a second set of strings to the puppet so that we can activate and manipulate the widget from the JavaScript console!
This technique allows you to do the following from the console:
- Change the widget's scope data
- Run widget scope functions
- Re-run the widget Server Script
- Right-click on the widget and choose "Inspect"
- In devtools Elements tab, click on the element with attribute widget=”widget”. It should be a few elements above the currently inspected element. This points the $0 scripting tool at the widget.
- In the Javascript console, run the following code:
var scopeRef = angular.element($0).scope();
Once you have a reference to the widget in the JavaScript console, you can take any piece of data in the widget's scope and just change it. After changing a value, run the AngularJS $apply() function on the scope to apply your changes to the page.
After getting a reference to the Global Objects Demo Widget in the console, run the following code:
scopeRef.data.prop1 = "Peach";
scopeRef.$apply();
Any function that is defined in the Client Scipt (client controller) of the widget is available from the widget's scope. This means that once you have a reference to a widget's scope in the console you will not only be able to change data in the scope object but you can also run any of the client controller functions!
The getPrettyData() function is defined in the Client Script of the Global Objects Demo Widget. Now that we have a reference to the widget's scope in the console, we can run the function directly from the JavaScript console.
Let's say that we've made some changes to the scope of the widget with the techniques above, we've got our reference to the widget in the console, and we want to see what happens when the server refreshes the data sent to the client controller. We can re-run the widget's Server Script from the console as per below:
scopeRef.server.refresh();
The client controller scripts for all widgets on the page can be found in the "Sources" panel of Chrome Developer Tools. If you look at the screen capture below, you'll notice that they are all listed under the "top" window then under the "(no domain)" section. Clicking on the script will open it in the Sources panel code editor window. Most of the widget client controller scripts are listed as <widget_id>.js, others will be listed by the id attribute value of the top level HTML element of the widget.
Once the client controller script is open in devtools you can begin debugging directly from there.
Navigate the to the following URL: https://.service-now.com/sp?id=demo_widget_example.
Open Chrome developer tools.
Click on the "Sources" panel in devtools.
Open the global-objects-demo-widget.js file
Between lines 7 and 8 add the following line of code:
alert("Server script now refreshed");
Right-click in the script editor window and Save. Do not refresh the page.
Click the server.refresh() button in the widget.
Notice the alert window pops up showing that you've been able to alter the widget directly from devtools!
Another great thing about having access to the client controller code from within devtools is that you can add in break points. Break points can be added to the code by clicking on the line numbers in the code editor window of the "Sources" panel.
Navigate the to the following URL: https://.service-now.com/sp?id=demo_widget_example
Open Chrome developer tools.
Click on the "Sources" panel in devtools.
Open the global-objects-demo-widget.js
Click on line number 15 to add in a break point.
Click on the server.get({collectionName: "presidents"}) button.
Notice that JavaScript execution stops directly at line 15.
Hover the mouse over the "data" in line 15 to inspect the response.
Resume JavaScript execution with the button to the right of the code editor window.
To follow along with the examples in this article, you'll need to first add the Global Objects Demo Widget to your developer instance. You can find the update set here. Download the update set and following the directions below.
To import the update set to your test instance:
- Click on "Retrieved Update Sets" in the Application Navigator.
- Click on the Related Link "Import Update Set from XML" at the bottom of the page.
- Click "Choose File", location the downloaded update set from the KB article and press the "Upload" button
- Click on the newly uploaded update set in the list of Retrieved Update Sets. The name will be "Service Portal Global Objects Demo"
- Click the Preview Update Set button in the header.
- Click on Commit Update Set. To run the tests, it's good to have two browser tabs open; one with the widget's code and preview pane and the other with the demo page showing.
Tab 1: https://.service-now.com/sp_config?id=widget_editor&sys_id=072cfcbc4f04130050d128201310c7d7&spa=1
Tab 2: https://.service-now.com/sp?id=demo_page
In the widget editor, you can enable a preview pane to test any changes that you've made to the widget. To do this click on the hamburger menu at the top right of the editor and select "Enable Preview". Then just use the eye button toggle the widget preview on and off.
After every test remember to remove any changes made and resave the widget.