
- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
on 04-12-2018 10:44 AM
Please post comments and questions via the Comment link below.
- 8,276 Views

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
The issue pops up as soon as the widget is loaded... The widget is loaded in an embedded widget...
Could you attach your widget to the post?
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
I posted this in the general conference community, but maybe it's better in a smaller group ... anyone here a runner? I went out this morning around 5:30 and realized it would be nice to have some company while navigating the - interesting - humanity on the strip at that hour.
I did 4 this morning at around a 9 min/mile pace. Thought I'd like to stretch out to around 6 if possible.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Would love to but I'm an old/slow runner getting back into it and am a 12-13 min mile runner that's still doing 3-5 min run/1-2 min walk intervals. I'll stay with the treadmill but enjoy and run safe.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Sure, its only a simple tester widget
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
in course "service portal advanced", p90 mentions using a custom $scope, like:
spUtil.refresh($scope); // same as c.server.refresh() but passes a custom $scope
when i find out what that is / what it's good for, i will try to update this.

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Here is an article from W3Schools which may help explain $scope: https://www.w3schools.com/angular/angular_scopes.asp
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
I cant even get it to work when replacing c.server.update with spUtil.update.
Dont really see the point in sending the scope with the function. Then again, I actually enjoy using c.server.get()

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Another article which may help understand AngulrJS $scope can be found at: https://www.tutorialspoint.com/angularjs/angularjs_scopes.htm
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Theoretically, it would enable you to get hold of a scope from another widget, for example, and pass that scope to the server. I personally have not yet found a use-case for this, but maybe someone else will have an example. 🙂

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Lab 2.4 -- In server side we used input variable. Where is it defined ? Is "input" a default angular variable ?
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
The input object is a special Angular object. See page 96 in the book for more details
c.data.myVar in the client controller is accessed in server side as input.myVar

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Yay
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
'input', 'options', and 'data' aren't Angular-specific constructs, but they are native to Service Portal. They will always be available in server & client script on widgets without any extra effort on your part.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Also if you run into errors where "input is undefined"; be sure to wrap your input work in an "if(input) { }" block.... For the server side script*
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Oh, I didn't know that! Thanks Ben!

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hey Room C, Martin put together some example scripts on filtering, orderBy and how to use both at the same time. Create a Test Widget and copy-paste this code into the HTML Template and Client Script editors to see it in action.
HTML Template
<div>
<!-- your widget template -->
<input name="q" type="text" placeholder="Search" ng-model="c.first" autocomplete="off" uib-typeahead="item as item.primary for item in c.getResults($viewValue)" typeahead-wait-ms="250" typeahead-focus-first="false" typeahead-on-select="c.onSelect($item, $model, $label)" typeahead-template-url="sp-typeahead.html" typeahead-popup-template-url="sp-typeahead-popup.html" class="form-control input-typeahead ng-pristine ng-untouched ng-valid ng-empty" title="Search" role="textbox" aria-label="Search" tabindex="0" aria-haspopup="true" aria-autocomplete="list" aria-owns="typeahead-75-1695" data-aria-expanded="false" aria-invalid="false">
<select ng-model="c.orderBy" class="form-control">
<option value="first">First</option>
<option value="last">Last</option>
</select>
<ul class="list-group">
<li ng-repeat="user in c.data.users| filter:c.first | orderBy:c.orderBy" class="list-group-item">{{user.first}} - {{user.last}}</li>
</ul>
</div>
Client Script
function($scope) {
/* widget controller */
var c = this;
c.data.users = [];
c.data.users.push({'first':'Bob','last':'Smith'})
c.data.users.push({'first':'Jane','last':'Doe'})
c.data.users.push({'first':'Fred','last':'Luddy'})
$scope.search = function(item) {
// Check the filter value against number and description
if (!c.filter || item.first.toUpperCase() == c.filter.toUpperCase() ){
return true;
}
return false;
};
}
Thanks Martin!!
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
On page 105 shouldn't the registrationExists function also query the event that the user is trying to register for? Otherwise they can only register for one event and not others. The current query looks for the email address being used for ANY event.

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
When you create a new Widget, what is suppose to happen if you select the option Create Test Page ? It is related with automated tests ?
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
It creates a brand new page, adds a container, a column and your new widget. Its not for automated testing, but rather for development purposes or if you want to add the widget to a new page anyway

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
@karen - please take a look at this. Thanks!
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Nate speaks the truth! 'input' only appears once you've performed a server.update() or the like. It does not exist on instantiation of a widget, only 'data' and 'options' exist at that point.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Nice catch!
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
I believe it's a bit of "magic" that ServiceNow is applying behind the scenes. The "data" object in the client script becomes the "input" object in the server script. (someone fact-check me if I'm wrong)
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
You got it right. Upon server.update(), SN passes the 'c.data' object from the client script up to the server script as 'input'. The server script can then do it's thing with the 'input' object, refresh the 'data' object, and then pass 'data' back to the client script.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Seems like Page 114 (one-time binding of AngularJS expressions) doesn't properly demo the "::" feature of AngularJS.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
If the table doesn't honour the cloud-widgets background colour, check which portal you are opening the page on. If it's not cloudevents you will have a bad time.

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
thks again

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
What exactly is $sp ?
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
If you are running behind and need some catch-up code, visit http://sp.ht4.org/. Solution code will be posted there shortly after you should have already completed. 🙂
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Check this out:
https://docs.servicenow.com/bundle/kingston-application-development/page/app-store/dev_portal/API_reference/GlideSPScriptableScoped/concept/c_GlideSPScriptableScopedAPI.html
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Here it was described as the Service Portal version of gs
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Yep, basically a server-side API, akin to a Script Include.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Lab 3.1:
Will c.updatedRegs be used in the future Labs? They currently have no function.
I have used them to highlight the changed record:
In the "Table Summary" Widget, HTML:
Replace:
<tr ng-repeat="record in c.data.records | orderBy : c.orderCol : c.sortOrder">
With:
<tr ng-repeat="record in c.data.records | orderBy : c.orderCol : c.sortOrder"
ng-class="{'highlighted':c.updatedRegs[record.sys_id]}">
And add this in the CSS:
.highlighted {
background:#dff0d8;
}
And might as well change the $timeout time from 6000 to 500 for a "flash"
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
We just did something similar up here at the front desk. 🙂
It appears that the client code was written for just such functionality, but it was forgotten in the HTML. Nice job, and a great 'extra credit' task for anyone else in the class!

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Did you also need to change "changeObj" in the client script to "updateObj"?

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
In module 3 we talk about the syntax of using scripted default options. A good example of an OOTB widget which does this is widget-ticket-conversation
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Interesting. on line 4-5 where its using this, should it have the $sp.getParameter as the second option to override the widget options instead of having the options as second? Since that can be supplied by a redirect URL...
e.g.
data.sys_id = input.sys_id || $sp.getParameter("sys_id") || options.sys_id;
?

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
TYPO FOUND IN LAB 3.1
Hi Guys, I found a typo in the Lab 3.1, more specifically, on page 134.
In the code for the record watch, it asks us to use the below:
spUtil.recordWatch($scope, c.data.table, '', function(updateObj){
//some code here(...), then:
/*add sys_ids of any changed records to an array
this will allow us to highlight them in the HTML template*/
c.updateRegs[changeObj.data.sys_id] = true;
$timeout(function(){
c.updatedRegs[changeObj.data.sys_id] = false;
}, 6000);
});
But if you pay close attention, changedObj is not defined anywhere and it won't result in anything. The record watch function returns the data in the param, so we should use that one, (updatedObj) instead. Here is the corrected code to be used:
spUtil.recordWatch($scope, c.data.table, '', function(updateObj){
//some code here(...), then:
/*add sys_ids of any changed records to an array
this will allow us to highlight them in the HTML template*/
c.updateRegs[updateObj.data.sys_id] = true;
$timeout(function(){
c.updatedRegs[updateObj.data.sys_id] = false;
}, 6000);
});
This won't affect completion of the lab since record watch is still running and enabling the lightning bulb. But it will prevent the updateRegs object to actually store any data in it. (Not sure if this will be needed for any of tomorrow's labs).
Hope this help! 🙂

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Lab 3.2 - Display fields
The columns are not respecting the order of display fields. Any idea how to fix it ?
Last name | Company | Updated | Event | First name | |
---|---|---|---|---|---|
Luddy | Cloud Dimensions | 2017-11-20 08:30:59 | Infinity Advanced Development | Fred | fred.luddy@cloudd.com |
Anglin | Cloud Dimensions | 2017-11-20 08:31:58 | Infinity Advanced Development | Beth | beth.anglin@cloudd.com |
Bennet | Cloud Dimensions | 2017-11-20 08:31:47 | Infinity Advanced Development | Jerrod | jerrod.bennet@cloudd.com |
Goodliffe | Cloud Dimensions | 2017-11-20 08:32:04 | Infinity Advanced Development | Don | don.goodliffe@cloudd.com |
FIRIFAFIRIFA | afaf | 2018-05-06 16:33:09 | Infinity Advanced Development | IT WILL WORK4 | fegasdasda@asdas.com |
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
This has to do with how the data is fed into the ng-repeat. It's being fed as an unordered JSON object - therefore, the column order is semi-random. It could be done in a more orderly fashion by using an array instead. In the real world, this would be the better way to go about it. Migrating to this could be a nice 'extra credit' exercise, if you want to try it out.

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hey Thais! To improve this even more, you can add an ng-class to the table row, so that the row is highlighted when it is updated. The code doesn't actually do anything otherwise! See the screenshot below for an example. The "highlight" class is defined in another lab to give the row a different background colour.

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Good morning all - if anyone left something in the room yesterday, it has most likely been moved to lost and found. This is on the same level as breakfast and registrations.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
This bothered me yesterday too. As Ben said, the object that is returned by $sp.getFieldsObject isnt an array unfortunately.
You "only" need to convert the Object into an Array.
Here is my Version...
Server Script:
Old:
data.labels=$sp.getFieldsObject(gr,input.fields);
New:
data.labels = [];
var labels = $sp.getFieldsObject(gr, input.fields);
for (var label in labels) {
data.labels.push({"key":label,
"value":labels[label].label});
}
HTML:
Here you have to replace the (key, val) with a variable.
And then call the values directly.
Here is my HTML under Step 5:
<table class="table cloud-widgets"
ng-if="c.data.records">
<thead>
<tr>
<th ng-repeat="l in c.data.labels"
ng-click="c.changeSortCol(l.key)">{{l.value}}
<span ng-show="c.orderCol==l.key">
<span class="fa fa-sort-asc"
ng-show="!c.sortOrder"></span>
<span class="fa fa-sort-desc"
ng-show="c.sortOrder"></span>
</span>
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="record in c.data.records | orderBy : c.orderCol : c.sortOrder"
ng-class="{'highlight':c.updatedRegs[record.sys_id]}">
<td ng-repeat="l in c.data.labels">{{record[l.key]}}</td>
</tr>
</tbody>
</table>
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Thanks for posting this, Oliver! We had a number of folks ask about it yesterday - this solution will be helpful.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Thanks Ben 🙂
On a small side note: There is no real point in adding "event" in the display fields as the data is being aggregated by it. But the display fields are a matter of taste

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Good Morning ! In lab 3.3 - item C 6 Is there a reason not to use if (!input) { } ?
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
You can gladly use the if (!input) {}, but in this case, we know the widget will never have a c.server.update/refresh/get call and so input would never be filled. If you know that your widget will be having server calls from the client side, then its surely suggested to have input and !input blocks

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Good morning Room2 - please send any music requests through and our DJ might be able to accommodate!

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Otherwise I am going to start playing some weird Australian psychedelic rock music.