The purpose of this blog is to illustrate what is Widget Communication in Service Portal and how it plays an important role in communication amongst widgets.

Widget communication:

Widgets make up the functionality of Portal page. It outlines what information a consumer can see and what exactly the Portal does. It is also reusable. At times, these widgets need to communicate with one another. Widgets can communicate with each other in two ways:

  • Communication Through Events
  • Communication Through URL

Widget communication through AngularJS Events ($broadcast, $emit, and $on):

To get information about events occurring within other widgets, AngularJS practice a ‘Publish and Subscribe’ approach for handling events.  This can be accomplished through the use of $broadcast, $emit, and $on methods provided by Angular.js. Events can notify when,

  • Record selected
  • Changed value
  • Data deleted
  • Data added
  • And more….

Work with events in AngularJS using these functions:

  • $emit(): Send an event up the scope hierarchy
  • $broadcast (): Send down the scope hierarchy
  • $on(): Listen for events of a particular type

Above approach exists on $scope and $rootScope. Widget controllers work as siblings while working with multiple Widgets on a page. To emit and listen for events, use the parent of all scopes, $rootScope.

Let’s start by two widgets.

Widget 1: Incident List.

Widget 2:  Incident Body

Create Incident List widget using below code:

IN HTML:

<div class=”panel panel-default”>
<div class=”panel-heading clearfix”>
<h3 class=”panel-title pull-left”>
INCIDENT
</h3>
</div>
<div class=”list-group”>
<a class=”list-group-item” ng-click=”c.selectIncident($index)”  ng-repeat=”incident in data.incidents” >
<h4 class=”list-group-item-heading”>
{{incident.number}}
</h4>
<p class=”list-group-item-text”>
{{incident.short_description}}
</p>
</a>
</div>

IN Client script:

function($rootScope,$scope,$location,spUtil) {
var c = this;
c.selectIncident = function(idx) {
var id = c.data.incidents[idx].sys_id;
console.log(‘Incidsent ID: ‘ + id);
$rootScope.incidentID = id;
$rootScope.$emit(‘selectIncident’, id);
}
}

In the above script, $emit() method is used to publish the event. The event used here is ‘selectIncident’. One can give any name to the event.

IN Server Script:

(function() {
data.incidents = [];
var inc = new GlideRecord(‘incident’);
inc.orderByDesc(‘sys_created_on’);
inc.setLimit(10);
inc.query();
while (inc.next()) {
var incident = {};
$sp.getRecordDisplayValues(incident,inc,’number,short_description,sys_id’);
data.incidents.push(incident);
}
})();

Create Incident Body widget using below code:

IN HTML Template:

<div class=”form-group”>
Number<input type=”text” ng-model=”c.data.number” class=”form-control” id=”usr”  >
</div>
<div class=”form-group”>
Short Description <textarea class=”form-control” id=”short” ng-model=”c.data.shortDescription”></textarea></div>

IN Client Script:

function(spUtil,$rootScope) {
/* widget controller */
var c = this;
$rootScope.$on(‘selectIncident’, function(event,data) {
Console.log(“event received…”+$rootScope.incidentID)
c.server.get({
action: ‘getIncident’,
incID: $rootScope.incidentID
}).then(function(r) {
c.data.number = r.data.incident.number;
c.data.shortDescription = r.data.incident.short_description;
});
});
}

In the above script, $on() method is used to respond to the event.

IN Server Script:

(function() {
if (input && input.incID) {
var inc = new GlideRecord(‘incident’);
if (inc.get(input.incID)) {
if (input.action == ‘getIncident’){
data.incident = {};
$sp.getRecordValues(data.incident, inc, “number,
short_description,sys_id”);                                                             }                                         }
}
})();

Add both widget to portal page. After clicking on the record from Incident List widget, it will generate event (‘selectIncident’) and send it to the Incident body Widget by using $emit() method. The Incident body event listen to that event using $on() in client script. The client script calls sever using c.server.get() method and passes custom input, data received from Incident list(sys_id). The server script glides the Incident table with the sys_id and stores the parameters in data object. The response from server is passed to client script using data object in response. The parameters from response are assigned to HTML elements in client script.

As console.log() method is used in both the widgets, one can see log messages in console.

Widget communication through URL:

Widget Communication through URL occurs by utilizing the parameter passed in URL(ex:sys_id). One can pass the sys_id of record displayed in list of Incident List widget. Use $location.search() method to set the URL with record sys_id. Once the URL is set with the sys_id of record, one can use that sys_id in incident body widget. To get the URL parameter in server script, use $sp.getParameter(“sys_id”). Modify the code provided in client script of incident list widget and server script of incident body widget  as below:

Incident List Widget(client script):

function($rootScope,$scope,$location,spUtil) {
var c = this;
c.selectIncident = function(idx) {
var id = c.data.incidents[idx].sys_id;
$location.search(“?id=your_page_id&sys_id=”+id);
}
}

Incident Body Widget(client script):

function(spUtil,$rootScope) {
/* widget controller */
var c = this;
c.server.update().then(function(r) {
c.data.number = r.data.incident.number;
c.data.shortDescription = r.data.incident.short_description;
});
}

Incident Body Widget(server script):

(function() {
Data.id=$sp.getParameter(“sys_id”);
var inc = new GlideRecord(‘incident’);
if (inc.get(Data.id)) {
data.incident = {};
$sp.getRecordValues(data.incident, inc, “number, short_description,sys_id”);
}
}
}
})();