- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
ā04-16-2020 04:25 AM
Hi
how can we communicate between two widgets in servicenow portal , I need it for my portal task .
Solved! Go to Solution.
- 3,294 Views

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
ā04-17-2020 12:45 AM
Hi ruksar
In order to acheive this you can follow these steps
Step 1: Create a portal or use an existing one.
If you have a portal you are already working with just use that or to create a sample one to play with. Attaching a screenshot of my example portal.
Step 2: Create a Service Portal page and add that to your example portal.
For demo purpose, I am going to create a new page give it a name/id and add that to my portal we created in the previous step.
Now let's start creating our widgets.
Step 3: Create Widget 1
Click on widgets under "Service Portal" application menu (or you can also create widgets using widget editor). Create a new widget by clicking on the new button.
Below is the example widget I have created.
Please use the below snippets to create your widget
HTML:
<div>
<!-- your widget template -->
<div class=" pill-background row">
<div class="each-pill" ng-class="{'active':c.selectedPill == 'requests'}" ng-click="selectPill('requests')">
<i class="fa fa-2x fa-list " aria-hidden="true"></i>
<p class="remove-margin">All Requests</p>
</div>
<div class="each-pill" ng-class="{'active':c.selectedPill == 'create'}" ng-click="selectPill('create')">
<i class="fa fa-2x fa-wrench " aria-hidden="true"></i>
<p class="remove-margin">Create Request</p>
</div>
<div class="each-pill" ng-class="{'active':c.selectedPill == 'contact'}" ng-click="selectPill('contact')">
<i class="fa fa-2x fa-phone " aria-hidden="true"></i>
<p class="remove-margin">Contact</p>
</div>
</div>
</div>
As you can see div "each-pill" has ng-click to function "selectPill". There is ng-class to show the difference between selected/unselected pill
Client Controller:
function($rootScope,$scope,$timeout) {
/* widget controller */
var c = this;
c.selectedPill = 'requests'; // When page loads, default pill selected
/*broadcast to other widgets after waiting for 500 milliseconds,
just to make sure other widgets are loaded and ready to listen when we broadcast.
*/
$timeout(function(){
$rootScope.$broadcast('showHideWidget', 'requests');
},500);
//broadcast the selection when ever cliked on each pill
$scope.selectPill = function(selection){
c.selectedPill = selection;
$rootScope.$broadcast('showHideWidget', selection);
};
}
In script above I have used $rootScope.$broadcast to notify other widgets, we can either use $rootScope.$broadcast or $rootScope.$emit.
Keep in mind $rootScope.$broadcast will notify all $rootScope.$on and $scope.$on
$rootScope.$emit will only notify $rootScope.$on.This is the syntax $broadcast/$emit
//firing an event
$rootScope.$broadcast('myCustomEvent', 'data');
data can be a JSON object, in our case its just a string.
//listening for an event
$scope.$on('myCustomEvent', function (event, data) {
console.log(data); // 'Data to send'
});
OR
$rootScope.$on('myCustomEvent', function (event, data) {
console.log(data); // 'Data to send'
});
CSS/SASS:
//Make sure sp-landing-back.jpg is in images table
.pill-background {
background: url(sp-landing-back.jpg) no-repeat center center fixed;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
height: 300px;
display: flex;
align-items: center;
justify-content: space-around;
.each-pill {
&.active {
color: #c70000;
}
height:150px;
width:200px;
background:#ddd;
padding:50px;
text-align:center;
border-radius:4px;
cursor:pointer;
p{
margin-top:5px;
}
}
}
.color-red {
color: #c70000;
}
.remove-margin {
margin-bottom: 0px;
}
After populating your widget with above code, go ahead and save it.
Widget 1 looks like this and you can see three pill boxes, clicking on them will emit/broadcast information to all other widgets. By default "All requests" pill is selected when the page loads.
Step 4: Create Widget 2 (All requests)
HTML:
<div ng-if="showWidget == 'requests'">
<div class="container">
<!-- your widget template -->
<div class="col-md-10 center-div">
<h3 style="display:inline-block;float:left;">Requests</h3>
<div ng-repeat="incident in data.requestList | limitTo:5" class="each-incident">
<h4></h4>
<p style="margin-bottom:0px;"></p>
</div>
</div>
</div>
The first line of this html has ng-if. Based on "data" broadcasted with the event, these widgets are shown/hidden.
Client Controller:
function($scope,$rootScope,$timeout) {
/* widget controller */
var c = this;
$scope.showWidget = "";
//Listening for "showHideWidget" event
$rootScope.$on('showHideWidget', function(event,data) {
$timeout(function(){
$scope.showWidget = data;
});
});
}
CSS:
.each-incident{
display:flex;
justify-content:space-between;
align-items:center;
padding:10px;
border-top:1px solid #ddd;
clear:both;
}
.center-div{
float: none;
margin-left: auto;
margin-right: auto;
}
Server script:
(function() {
/* populate the 'data' object */
/* e.g., data.table = $sp.getValue('table'); */
data.requestList = [];
var gr = new GlideRecord('change_request');
gr.addQuery('category','Hardware');
gr.query();
while(gr.next()){
var temp = {};
temp.number = gr.number.toString();
temp.short_desc = gr.short_description.toString();
data.requestList.push(temp);
}
})();
Step 5: Create Widget 3 (Create request)
HTML:
<div ng-if="showWidget == 'create'" class="col-md-10 center-div">
<h3 style=" border-bottom: 1px solid #ddd;padding-bottom:5px; ">Create Request</h3>
<form class="form-horizontal">
<div class="form-group">
<label for="" class="col-sm-2 control-label">Request Number</label>
<div class="col-sm-10">
<input type="text" class="form-control" placeholder="Number" autocomplete="off"> </div>
</div>
<div class="form-group">
<label for="" class="col-sm-2 control-label">Short Description</label>
<div class="col-sm-10">
<input type="text" class="form-control" placeholder="Short Description" autocomplete="off"> </div>
</div>
<div class="form-group">
<label for="" class="col-sm-2 control-label">Description</label>
<div class="col-sm-10">
<textarea class="form-control" rows="3"></textarea>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label>
<input type="checkbox"> High priority </label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button class="btn btn-default">Submit</button>
</div>
</div>
</form>
</div>
Client Controller:
function($scope,$rootScope,$timeout) {
/* widget controller */
var c = this;
$scope.showWidget = "";
$rootScope.$on('showHideWidget', function(event,data) {
$timeout(function(){
$scope.showWidget = data;
});
});
}
CSS:
.center-div{
margin-left: auto;
margin-right: auto;
float:none;
}
Step 6: Create Widget 4 (Contact)
HTML:
<div ng-if="showWidget == 'contact'">
<div class="container">
<!-- your widget template -->
<div class="col-md-10 center-div">
<h3 style=" border-bottom: 1px solid #ddd;padding-bottom:5px; ">Contact</h3>
<div class="flex-display col-md-9">
<div class="">
<h4>Address:</h4>
<p class="remove-margin">XYZ Company</p>
<p class="remove-margin">123 Washington st</p>
<p class="remove-margin">Washington</p>
</div>
<div>
<div class="">
<h4>Email:</h4>
<a href="javascript:void(0)">abc@abc.com</a>
</div>
<div class="">
<h4>phone</h4>
<a href="javascript:void(0)">(123)4567890</a>
</div>
</div>
</div>
</div>
</div>
Client Controller:
function($scope,$rootScope,$timeout) {
/* widget controller */
var c = this;
$scope.showWidget = "";
$scope.$on('showHideWidget', function(event,data) {
$timeout(function(){
$scope.showWidget = data;
});
});
}
CSS:
.flex-display{
display:flex;
justify-content:space-between;
padding:10px;
clear:both;
margin-left: auto;
margin-right: auto;
float: none;
}
.center-div{
float: none;
margin-left: auto;
margin-right: auto;
}
.remove-margin{
margin-bottom:0px;
}
Step 7: Adding our widgets to Service Portal page.
The last and final step is to add the widgets we created to a Service portal page using Service portal designer.
click on "Service portal configuration" which takes you to a new page with a list of options.
Select designer, A new page opens up and u can see all the "Service portal pages", search for your page, in my case its "sp_examples_homepage"
Now in the page designer view drag and drop "Container" on the page followed by 12 column layout. On the left side, you can see all the widgets available for us to use, search for our widget we created in step 3 (Menu pills) and drag and drop that into the 12 column layout.
Drag and drop another 12 column layout below the "Menu Pills" widget. Search for our widgets we created in step 4,5,6 (All requests, Create request, Contact widget) and drag and drop them onto the 12 column layout. It should look something like this.
We have successfully added our widgets to the page. Now let's check out this widget in action. Click on "portals" under "Service Portal" Application menu. Select the portal we used for this tutorial and hit "try it" button at the bottom.
You should see your Menu pills Widget communicating with other widgets to hide/show them.
This is just a simple demonstration of how widgets can talk to each other. $rootScope.$broadcast('myCustomEvent', 'data'); can be very useful, when you want to send data to other widgets.
Please mark my answer correct and helpful,If this helps you in any way.
Saurabh

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
ā04-16-2020 05:50 PM
Hi Ruksar,
Your question would be answered depending on which relation of those widgets:
1. If widget B is embeded in widget A:
- You can pass to the object option of widget A as below.
2. If they are just sibling/parent-child in page component/DOM
- You can use some library like $rootscope in client script and find the scope of widget you want to connect.
- In there, you can get $scope.data or $scope. whatever it contains.
Hope might answer would help.
Please mark correct if you find it helpful.
Cuong Phan
DXC Consultant
Cuong Phan
ServiceNow Technical Lead

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
ā04-16-2020 05:58 PM
What exactly you are trying to do?
you can use broadcast to communicate between 2 widgets.
https://serviceportal.io/using-events-communicate-widgets/
not clear about task so also refer to https://community.servicenow.com/community?id=community_article&sys_id=4c639526db5d7b4ce0e80b55ca961...

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
ā04-16-2020 10:28 PM
Hey Ruksar,
I would suggest you to go through the ServiceNow Learning Plan on Custom Widget Creation Click here.
Also if you would like something extra go to Widget Comm.
This is the best example you can try your hands on: https://serviceportal.io/using-events-communicate-widgets/
I have created many Widgets as well as established communication between them, widgets on same page as well as communication between Widgets on different page of portals. So if you have any query you can ask me. But 1st i would suggest you to try the above links.
Also please don't use $broadcast rather you should use $emit to send data from one widget to another and to receive the info always use $on.
If i was able to answer your query then please mark my answer Correct and Helpful.
Thanks and Regards:
Utpal Dutta

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
ā04-17-2020 12:45 AM
Hi ruksar
In order to acheive this you can follow these steps
Step 1: Create a portal or use an existing one.
If you have a portal you are already working with just use that or to create a sample one to play with. Attaching a screenshot of my example portal.
Step 2: Create a Service Portal page and add that to your example portal.
For demo purpose, I am going to create a new page give it a name/id and add that to my portal we created in the previous step.
Now let's start creating our widgets.
Step 3: Create Widget 1
Click on widgets under "Service Portal" application menu (or you can also create widgets using widget editor). Create a new widget by clicking on the new button.
Below is the example widget I have created.
Please use the below snippets to create your widget
HTML:
<div>
<!-- your widget template -->
<div class=" pill-background row">
<div class="each-pill" ng-class="{'active':c.selectedPill == 'requests'}" ng-click="selectPill('requests')">
<i class="fa fa-2x fa-list " aria-hidden="true"></i>
<p class="remove-margin">All Requests</p>
</div>
<div class="each-pill" ng-class="{'active':c.selectedPill == 'create'}" ng-click="selectPill('create')">
<i class="fa fa-2x fa-wrench " aria-hidden="true"></i>
<p class="remove-margin">Create Request</p>
</div>
<div class="each-pill" ng-class="{'active':c.selectedPill == 'contact'}" ng-click="selectPill('contact')">
<i class="fa fa-2x fa-phone " aria-hidden="true"></i>
<p class="remove-margin">Contact</p>
</div>
</div>
</div>
As you can see div "each-pill" has ng-click to function "selectPill". There is ng-class to show the difference between selected/unselected pill
Client Controller:
function($rootScope,$scope,$timeout) {
/* widget controller */
var c = this;
c.selectedPill = 'requests'; // When page loads, default pill selected
/*broadcast to other widgets after waiting for 500 milliseconds,
just to make sure other widgets are loaded and ready to listen when we broadcast.
*/
$timeout(function(){
$rootScope.$broadcast('showHideWidget', 'requests');
},500);
//broadcast the selection when ever cliked on each pill
$scope.selectPill = function(selection){
c.selectedPill = selection;
$rootScope.$broadcast('showHideWidget', selection);
};
}
In script above I have used $rootScope.$broadcast to notify other widgets, we can either use $rootScope.$broadcast or $rootScope.$emit.
Keep in mind $rootScope.$broadcast will notify all $rootScope.$on and $scope.$on
$rootScope.$emit will only notify $rootScope.$on.This is the syntax $broadcast/$emit
//firing an event
$rootScope.$broadcast('myCustomEvent', 'data');
data can be a JSON object, in our case its just a string.
//listening for an event
$scope.$on('myCustomEvent', function (event, data) {
console.log(data); // 'Data to send'
});
OR
$rootScope.$on('myCustomEvent', function (event, data) {
console.log(data); // 'Data to send'
});
CSS/SASS:
//Make sure sp-landing-back.jpg is in images table
.pill-background {
background: url(sp-landing-back.jpg) no-repeat center center fixed;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
height: 300px;
display: flex;
align-items: center;
justify-content: space-around;
.each-pill {
&.active {
color: #c70000;
}
height:150px;
width:200px;
background:#ddd;
padding:50px;
text-align:center;
border-radius:4px;
cursor:pointer;
p{
margin-top:5px;
}
}
}
.color-red {
color: #c70000;
}
.remove-margin {
margin-bottom: 0px;
}
After populating your widget with above code, go ahead and save it.
Widget 1 looks like this and you can see three pill boxes, clicking on them will emit/broadcast information to all other widgets. By default "All requests" pill is selected when the page loads.
Step 4: Create Widget 2 (All requests)
HTML:
<div ng-if="showWidget == 'requests'">
<div class="container">
<!-- your widget template -->
<div class="col-md-10 center-div">
<h3 style="display:inline-block;float:left;">Requests</h3>
<div ng-repeat="incident in data.requestList | limitTo:5" class="each-incident">
<h4></h4>
<p style="margin-bottom:0px;"></p>
</div>
</div>
</div>
The first line of this html has ng-if. Based on "data" broadcasted with the event, these widgets are shown/hidden.
Client Controller:
function($scope,$rootScope,$timeout) {
/* widget controller */
var c = this;
$scope.showWidget = "";
//Listening for "showHideWidget" event
$rootScope.$on('showHideWidget', function(event,data) {
$timeout(function(){
$scope.showWidget = data;
});
});
}
CSS:
.each-incident{
display:flex;
justify-content:space-between;
align-items:center;
padding:10px;
border-top:1px solid #ddd;
clear:both;
}
.center-div{
float: none;
margin-left: auto;
margin-right: auto;
}
Server script:
(function() {
/* populate the 'data' object */
/* e.g., data.table = $sp.getValue('table'); */
data.requestList = [];
var gr = new GlideRecord('change_request');
gr.addQuery('category','Hardware');
gr.query();
while(gr.next()){
var temp = {};
temp.number = gr.number.toString();
temp.short_desc = gr.short_description.toString();
data.requestList.push(temp);
}
})();
Step 5: Create Widget 3 (Create request)
HTML:
<div ng-if="showWidget == 'create'" class="col-md-10 center-div">
<h3 style=" border-bottom: 1px solid #ddd;padding-bottom:5px; ">Create Request</h3>
<form class="form-horizontal">
<div class="form-group">
<label for="" class="col-sm-2 control-label">Request Number</label>
<div class="col-sm-10">
<input type="text" class="form-control" placeholder="Number" autocomplete="off"> </div>
</div>
<div class="form-group">
<label for="" class="col-sm-2 control-label">Short Description</label>
<div class="col-sm-10">
<input type="text" class="form-control" placeholder="Short Description" autocomplete="off"> </div>
</div>
<div class="form-group">
<label for="" class="col-sm-2 control-label">Description</label>
<div class="col-sm-10">
<textarea class="form-control" rows="3"></textarea>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label>
<input type="checkbox"> High priority </label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button class="btn btn-default">Submit</button>
</div>
</div>
</form>
</div>
Client Controller:
function($scope,$rootScope,$timeout) {
/* widget controller */
var c = this;
$scope.showWidget = "";
$rootScope.$on('showHideWidget', function(event,data) {
$timeout(function(){
$scope.showWidget = data;
});
});
}
CSS:
.center-div{
margin-left: auto;
margin-right: auto;
float:none;
}
Step 6: Create Widget 4 (Contact)
HTML:
<div ng-if="showWidget == 'contact'">
<div class="container">
<!-- your widget template -->
<div class="col-md-10 center-div">
<h3 style=" border-bottom: 1px solid #ddd;padding-bottom:5px; ">Contact</h3>
<div class="flex-display col-md-9">
<div class="">
<h4>Address:</h4>
<p class="remove-margin">XYZ Company</p>
<p class="remove-margin">123 Washington st</p>
<p class="remove-margin">Washington</p>
</div>
<div>
<div class="">
<h4>Email:</h4>
<a href="javascript:void(0)">abc@abc.com</a>
</div>
<div class="">
<h4>phone</h4>
<a href="javascript:void(0)">(123)4567890</a>
</div>
</div>
</div>
</div>
</div>
Client Controller:
function($scope,$rootScope,$timeout) {
/* widget controller */
var c = this;
$scope.showWidget = "";
$scope.$on('showHideWidget', function(event,data) {
$timeout(function(){
$scope.showWidget = data;
});
});
}
CSS:
.flex-display{
display:flex;
justify-content:space-between;
padding:10px;
clear:both;
margin-left: auto;
margin-right: auto;
float: none;
}
.center-div{
float: none;
margin-left: auto;
margin-right: auto;
}
.remove-margin{
margin-bottom:0px;
}
Step 7: Adding our widgets to Service Portal page.
The last and final step is to add the widgets we created to a Service portal page using Service portal designer.
click on "Service portal configuration" which takes you to a new page with a list of options.
Select designer, A new page opens up and u can see all the "Service portal pages", search for your page, in my case its "sp_examples_homepage"
Now in the page designer view drag and drop "Container" on the page followed by 12 column layout. On the left side, you can see all the widgets available for us to use, search for our widget we created in step 3 (Menu pills) and drag and drop that into the 12 column layout.
Drag and drop another 12 column layout below the "Menu Pills" widget. Search for our widgets we created in step 4,5,6 (All requests, Create request, Contact widget) and drag and drop them onto the 12 column layout. It should look something like this.
We have successfully added our widgets to the page. Now let's check out this widget in action. Click on "portals" under "Service Portal" Application menu. Select the portal we used for this tutorial and hit "try it" button at the bottom.
You should see your Menu pills Widget communicating with other widgets to hide/show them.
This is just a simple demonstration of how widgets can talk to each other. $rootScope.$broadcast('myCustomEvent', 'data'); can be very useful, when you want to send data to other widgets.
Please mark my answer correct and helpful,If this helps you in any way.
Saurabh