To get the content of an attachment, do the following:
var attch = new GlideRecord('sys_attachment');
attch.get(<sys_id>);
var gsa = new GlideSysAttachment();
var content = gsa.getContent(attch); //returns content as a string
gs.debug(content || "Failed!"); //Aint that a cool way to log?
There are cases where the attachment is huge and SN would not be able to process them all; GlideTextReader() will allow us to read through the content of the file, like below:
var attch = new GlideRecord('sys_attachment');
attch.get(<sys_id>);
var gsa = new GlideSysAttachment();
var stream = gsa.getContentStream(attch);
var reader = new GlideTextReader(stream);
var line;
var count = 0;
while(line = reader.readLine()){
count++;
}
gs.debug("Read "+count+" lines");
This is the key here: reader.readLine();
$emit - Emits for other widgets to receive - GOES UP - goes from child up to parent
$broadcast - Emits for other widgets to receive - GOES DOWN - goes from parent to child controller, from rootscope to subscopes
$on - widget that wait for the broadcast
$scope: It is like a local variable and it can be accessible only within the component eg. controller, service. when we want any variable to be used within the class or component or want without a reference to the containing class anyone can access that element, we should use $scope as it would not allow this variable to be accessible from outside. Widget-specific.
$rootscope: It is like the global variable and it can be accessible from everywhere.
a common property that can be shared with anyone no restrictions on accessibility. a shared resource that can be accessed from anywhere. accessible across all widgets.
$timeout: This service allows the developer to set some time delay before the execution of the function. $timeout always expects a function, like the below example. '2000' is the milliseconds before the function executes.
Example:
var app = angular.module('timeoutApp', []);
app.controller('timeoutCtrl', function ($scope, $timeout) {
$scope.text="Enter username and password to login"
$timeout(function () {
$scope.text = "Do not share your username and password with anybody";
}, 2000);
});
Cross-widget comm:
Scenario: Use a spinner icon when a particular item (widget) loads on the page.
How we do it: add the spinner in a blank widget, make it the await a broadcast (using $on) from the actual widget that decides if the spinner should show.
Widget 1 (The spinner widget):
The $on is to be used with the following format:
$rootscope.$on('eventName', function(event, data){})
The HTML section of the widget, using ng-if, checks the value of the $scope.showSpinner as below:
The $scope.showSpinner in this case is a simple boolean value. This can be given with any object type, and the function inside $scope.$on() is just logging what flows inside showSpinner. DO NOT confuse with the $scope.showSpinner and 'showSpinner' inside the $on function, as the former is data and the latter is the event that this widget is waiting for.
Widget 2:
Widget 2 is going to broadcast the 'showSpinner' event and its data:
Notice that broadcast is done as eventName, and the value that the event carries.
Additional learning:
$scope.create is the function that is being called from ng-change=create()
first thing in the function is to broadcast the event to the other widget, so that is wouldn't show the spinner
the $http is a function (in this context) to send a rest call
$http here has parameters in it for the method, endpoint URL, headers
Alternative to this is $http.get('url')
.then() is more like the if statement in angular, that says if the create function executes, then do this
other alternative to then is .success(), which is depriciated
.then() is better since it takes two parameter functions called success and failure
Live Widgets:
Widgets can have live updates using the spUtil.recordWatch()
recordWatch gets triggered everytime a server update happens.
Need to be careful about where we use this, since for example, if a simple list widget is used and we try re-ordering the records, lets say moving the 3rd record to 2nd position, the work to be done is re-order 1324 from 1234.
But in case a BR runs to update all 4 records to re-order them, the field watcher gets triggered 4 times. Now imagine the same for 100+ records. The portal would feel its its refreshing for a while (with the 3 dots on the banner)
Lets say there is a widget that shows count of records on a table, which can be manipulated with the table options and filter options.
a widget can be re-used with the help of this approach below. Using options to define the data - It can be re-used across multiple scenarios with the same widget. Widget Instance, duh!
this can be done by just opening the widget editor and adding option schema.
Server script:
data.tableName = options.tableName || 'incident';
data.filter = options.filter || '';
data.label = options.label || ''(no label)'';
var g = new GlideAggregate(data.table);
g.addAggregate('count')
g.addEncodedQuery(data.filter);
g.query();
if(g.next()){
data.count = parseInt(g.getAggregate('count'))}
Client script:
spUtil.recordWatch(c.data.tableName, c.data.filter, function(response){
console.log(response.data); //this will log all the data that changed, in the console
c.server.update();
})
HTML:
<div>
{{c.data.label}}
{{c.data.count}}
</div>
spUtil.recordWatch(c.data.tableName, c.data.filter, function(){}); - the filter parameter will limit the recordWatch to specifically watch for the filtered list of data, and not all data.
Something similar can be done with a table widget too (simple list):
Here, the first ng-repeat simply means that the HTML will keep typing rows until it finds labels, and the other repeats will list out the rows with values.
Check this for the code used for the count widget and a table widget:
Pagination in SP:
Pagination directive can be used for this: https://github.com/michaelbromley/angularUtils/tree/master/src/directives/pagination
ServiceNow blogs:
Important Links & snippets:
https://community.servicenow.com/community?id=community_blog&sys_id=e60eea2ddbd0dbc01dcaf3231f961972
ctrl + A, shift+tab auto-formats scripts, even HTML, SN script editor.
spUtil.addTrivialMessage() shows a message that fades away automatically.
'Demo data' field on the widget record helps test the widget.
Chuck's github link: bit.ly/sn-cls
Comments