© 2018 ServiceNow All Rights Reserved
Making Service Portal Widgets
Work Together
Travis Toulson
Sr. Architect
GlideFast Consulting
© 2016 ServiceNow All Rights Reserved 2Confidential
2
#Know18
© 2018 ServiceNow All Rights Reserved
Widgets are volatile,
self-obsessed, and
don’t play well with
others
Problem
© 2016 ServiceNow All Rights Reserved 3Confidential
3
#Know18
© 2018 ServiceNow All Rights Reserved
ng-app
ng-controller
container
row
column
rectangle
widget
The Design
Powerful widgets simplify
everything else
© 2016 ServiceNow All Rights Reserved 4Confidential
4
#Know18
© 2018 ServiceNow All Rights Reserved
BUT…
© 2016 ServiceNow All Rights Reserved 5Confidential
5
#Know18
© 2018 ServiceNow All Rights Reserved
© 2016 ServiceNow All Rights Reserved 6Confidential
6
#Know18
© 2018 ServiceNow All Rights Reserved
Massive
Widgets
Repetitive
Widgets
VS
© 2016 ServiceNow All Rights Reserved 7Confidential
7
#Know18
© 2018 ServiceNow All Rights Reserved
Embed widgets to
compose complex
behaviors
#1
© 2016 ServiceNow All Rights Reserved 8Confidential
8
#Know18
© 2018 ServiceNow All Rights Reserved
ç
Data Table Widget
- 7 Different Behaviors
- Over 300 lines of client
code
- Over 150 lines of server
code
© 2016 ServiceNow All Rights Reserved 9Confidential
9
#Know18
© 2018 ServiceNow All Rights Reserved
<div>
<sp-widget widget="data.filterBreadcrumbs">
</sp-widget>
</div>
var breadcrumbWidgetParams = {
table: data.table,
query: data.filter,
enable_filter: data.enable_filter
};
data.filterBreadcrumbs = $sp.getWidget(
'widget-filter-breadcrumbs',
breadcrumbWidgetParams);
HTML
Server Script
© 2016 ServiceNow All Rights Reserved 10Confidential
10
#Know18
© 2018 ServiceNow All Rights Reserved
<div>
<sp-widget widget="data.filterBreadcrumbs">
</sp-widget>
</div>
var breadcrumbWidgetParams = {
table: data.table,
query: data.filter,
enable_filter: data.enable_filter
};
data.filterBreadcrumbs = $sp.getWidget(
'widget-filter-breadcrumbs',
breadcrumbWidgetParams);
HTML
Server Script
© 2016 ServiceNow All Rights Reserved 11Confidential
11
#Know18
© 2018 ServiceNow All Rights Reserved
<div>
<sp-widget widget="data.filterBreadcrumbs">
</sp-widget>
</div>
var breadcrumbWidgetParams = {
table: data.table,
query: data.filter,
enable_filter: data.enable_filter
};
data.filterBreadcrumbs = $sp.getWidget(
'widget-filter-breadcrumbs',
breadcrumbWidgetParams);
HTML
Server Script
© 2016 ServiceNow All Rights Reserved 12Confidential
12
#Know18
© 2018 ServiceNow All Rights Reserved
<div>
<sp-widget widget="data.filterBreadcrumbs">
</sp-widget>
</div>
var breadcrumbWidgetParams = {
table: data.table,
query: data.filter,
enable_filter: data.enable_filter
};
data.filterBreadcrumbs = $sp.getWidget(
'widget-filter-breadcrumbs',
breadcrumbWidgetParams);
HTML
Server Script
© 2016 ServiceNow All Rights Reserved 13Confidential
13
#Know18
© 2018 ServiceNow All Rights Reserved
<div>
<sp-widget widget="data.filterBreadcrumbs">
</sp-widget>
</div>
var breadcrumbWidgetParams = {
table: data.table,
query: data.filter,
enable_filter: data.enable_filter
};
data.filterBreadcrumbs = $sp.getWidget(
'widget-filter-breadcrumbs',
breadcrumbWidgetParams);
HTML
Server Script
© 2016 ServiceNow All Rights Reserved 14Confidential
14
#Know18
© 2018 ServiceNow All Rights Reserved
<div>
<sp-widget widget="data.filterBreadcrumbs">
</sp-widget>
</div>
var breadcrumbWidgetParams = {
table: data.table,
query: data.filter,
enable_filter: data.enable_filter
};
data.filterBreadcrumbs = $sp.getWidget(
'widget-filter-breadcrumbs',
breadcrumbWidgetParams);
HTML
Server Script
© 2016 ServiceNow All Rights Reserved 15Confidential
15
#Know18
© 2018 ServiceNow All Rights Reserved
A “child scope” (prototypically)
inherits properties from its
“parent scope”
“
- AngularJS Developer Guide
© 2016 ServiceNow All Rights Reserved 16Confidential
16
#Know18
© 2018 ServiceNow All Rights Reserved
<a style="display: inline;" href>{{page.title}}</a>
Data Table Widget
HTML Template
© 2016 ServiceNow All Rights Reserved 17Confidential
17
#Know18
© 2018 ServiceNow All Rights Reserved
ng-app
ng-controller
container
row
column
rectangle
widget
{{page.title}}
Data Table Widget
doesn’t have a page
object?!?!
© 2016 ServiceNow All Rights Reserved 18Confidential
18
#Know18
© 2018 ServiceNow All Rights Reserved
Child Widgets inherit
functions and data
from their Parent
Widgets
© 2016 ServiceNow All Rights Reserved 19Confidential
19
#Know18
© 2018 ServiceNow All Rights Reserved
Structure application
models with Angular
Services
#2
© 2016 ServiceNow All Rights Reserved 20Confidential
20
#Know18
© 2018 ServiceNow All Rights Reserved
You can use services to organize
and share code across your app
“
- AngularJS Developer Guide
© 2016 ServiceNow All Rights Reserved 21Confidential
21
#Know18
© 2018 ServiceNow All Rights Reserved
1. Create the Angular Provider
2. Add it to the Widget’s Angular
Provider Related List
3. Inject the dependency into the
Client Script
Wire up a Service
© 2016 ServiceNow All Rights Reserved 22Confidential
22
#Know18
© 2018 ServiceNow All Rights Reserved
function($http) {
var incidents = [];
function reload() {
$http.get(‘/api/now/table/incident’)
.then(function(res) { incidents = res.result; });
}
function get() {
return incidents;
}
return {
‘reload’: reload,
‘get’: get
};
}
Service
Type: Service
Name: incidentService
© 2016 ServiceNow All Rights Reserved 23Confidential
23
#Know18
© 2018 ServiceNow All Rights Reserved
function($http) {
var incidents = [];
function reload() {
$http.get(‘/api/now/table/incident’)
.then(function(res) { incidents = res.result; });
}
function get() {
return incidents;
}
return {
‘reload’: reload,
‘get’: get
};
}
Service
Type: Service
Name: incidentService
© 2016 ServiceNow All Rights Reserved 24Confidential
24
#Know18
© 2018 ServiceNow All Rights Reserved
function($http) {
var incidents = [];
function reload() {
$http.get(‘/api/now/table/incident’)
.then(function(res) { incidents = res.result; });
}
function get() {
return incidents;
}
return {
‘reload’: reload,
‘get’: get
};
}
Service
Type: Service
Name: incidentService
© 2016 ServiceNow All Rights Reserved 25Confidential
25
#Know18
© 2018 ServiceNow All Rights Reserved
function($http) {
var incidents = [];
function reload() {
$http.get(‘/api/now/table/incident’)
.then(function(res) { incidents = res.result; });
}
function get() {
return incidents;
}
return {
‘reload’: reload,
‘get’: get
};
}
Service
Type: Service
Name: incidentService
© 2016 ServiceNow All Rights Reserved 26Confidential
26
#Know18
© 2018 ServiceNow All Rights Reserved
function($http) {
var incidents = [];
function reload() {
$http.get(‘/api/now/table/incident’)
.then(function(res) { incidents = res.result; });
}
function get() {
return incidents;
}
return {
‘reload’: reload,
‘get’: get
};
}
Service
Type: Service
Name: incidentService
© 2016 ServiceNow All Rights Reserved 27Confidential
27
#Know18
© 2018 ServiceNow All Rights Reserved
function($http) {
var incidents = [];
function reload() {
$http.get(‘/api/now/table/incident’)
.then(function(res) { incidents = res.result; });
}
function get() {
return incidents;
}
return {
‘reload’: reload,
‘get’: get
};
}
Service
Type: Service
Name: incidentService
© 2016 ServiceNow All Rights Reserved 28Confidential
28
#Know18
© 2018 ServiceNow All Rights Reserved
function (incidentService) {
var c = this;
incidentService.reload();
c.reload = function() {
incidentService.reload();
}
c.getIncidents = function() {
return incidentService.get();
}
}
Client Script
© 2016 ServiceNow All Rights Reserved 29Confidential
29
#Know18
© 2018 ServiceNow All Rights Reserved
function (incidentService) {
var c = this;
incidentService.reload();
c.reload = function() {
incidentService.reload();
}
c.getIncidents = function() {
return incidentService.get();
}
}
Client Script
© 2016 ServiceNow All Rights Reserved 30Confidential
30
#Know18
© 2018 ServiceNow All Rights Reserved
function (incidentService) {
var c = this;
incidentService.reload();
c.reload = function() {
incidentService.reload();
}
c.getIncidents = function() {
return incidentService.get();
}
}
Client Script
© 2016 ServiceNow All Rights Reserved 31Confidential
31
#Know18
© 2018 ServiceNow All Rights Reserved
function (incidentService) {
var c = this;
incidentService.reload();
c.reload = function() {
incidentService.reload();
}
c.getIncidents = function() {
return incidentService.get();
}
}
Client Script
© 2016 ServiceNow All Rights Reserved 32Confidential
32
#Know18
© 2018 ServiceNow All Rights Reserved
function (incidentService) {
var c = this;
incidentService.reload();
c.reload = function() {
incidentService.reload();
}
c.getIncidents = function() {
return incidentService.get();
}
}
Client Script
© 2016 ServiceNow All Rights Reserved 33Confidential
33
#Know18
© 2018 ServiceNow All Rights Reserved
<div ng-repeat=“inc in c.getIncidents()”>
<!-- Incident Template Here -->
</div>
Digest Loop
HTML Template
© 2016 ServiceNow All Rights Reserved 34Confidential
34
#Know18
© 2018 ServiceNow All Rights Reserved
Use Angular Events as
a last resort
#3
© 2016 ServiceNow All Rights Reserved 35Confidential
35
#Know18
© 2018 ServiceNow All Rights Reserved
Insanity Warning: scope depth-
first traversal. Yes, this code is a
bit crazy, but it works and we
have tests to prove it
“
- Line 1417, rootScope.js AngularJS Source Code
© 2016 ServiceNow All Rights Reserved 36Confidential
36
#Know18
© 2018 ServiceNow All Rights Reserved
ng-app
ng-controller
container
row
column
rectangle
widget
Event Propagation
$rootScope
$scope
$broadcast
$emit
$on
© 2016 ServiceNow All Rights Reserved 37Confidential
37
#Know18
© 2018 ServiceNow All Rights Reserved
But given that it’s a
stupid a** decision,
I’ve elected to ignore
it
© 2016 ServiceNow All Rights Reserved 38Confidential
38
#Know18
© 2018 ServiceNow All Rights Reserved
function ($scope) {
$scope.$on(‘incident.changed’,
function(event, data) {
// Do something!
});
}
function ($rootScope) {
$rootScope.$broadcast(‘incident.changed’, {});
}
Widget 2
Client Script
Widget 1
Client Script
© 2016 ServiceNow All Rights Reserved 39Confidential
39
#Know18
© 2018 ServiceNow All Rights Reserved
function ($scope) {
$scope.$on(‘incident.changed’,
function(event, data) {
// Do something!
});
}
function ($rootScope) {
$rootScope.$broadcast(‘incident.changed’, {});
}
Widget 2
Client Script
Widget 1
Client Script
© 2016 ServiceNow All Rights Reserved 40Confidential
40
#Know18
© 2018 ServiceNow All Rights Reserved
function ($scope) {
$scope.$on(‘incident.changed’,
function(event, data) {
// Do something!
});
}
function ($rootScope) {
$rootScope.$broadcast(‘incident.changed’, {});
}
Widget 2
Client Script
Widget 1
Client Script
© 2016 ServiceNow All Rights Reserved 41Confidential
41
#Know18
© 2018 ServiceNow All Rights Reserved
function ($scope) {
$scope.$on(‘incident.changed’,
function(event, data) {
// Do something!
});
}
function ($rootScope) {
$rootScope.$broadcast(‘incident.changed’, {});
}
Widget 2
Client Script
Widget 1
Client Script
© 2016 ServiceNow All Rights Reserved 42Confidential
42
#Know18
© 2018 ServiceNow All Rights Reserved
function ($scope) {
$scope.$on(‘incident.changed’,
function(event, data) {
// Do something!
});
}
function ($rootScope) {
$rootScope.$broadcast(‘incident.changed’, {});
}
Widget 2
Client Script
Widget 1
Client Script
© 2016 ServiceNow All Rights Reserved 43Confidential
43
#Know18
© 2018 ServiceNow All Rights Reserved
function ($scope) {
$scope.$on(‘incident.changed’,
function(event, data) {
// Do something!
});
}
function ($rootScope) {
$rootScope.$broadcast(‘incident.changed’, {});
}
Widget 2
Client Script
Widget 1
Client Script
© 2016 ServiceNow All Rights Reserved 44Confidential
44
#Know18
© 2018 ServiceNow All Rights Reserved
function ($scope) {
$scope.$on(‘incident.changed’,
function(event, data) {
// Do something!
});
}
function ($rootScope) {
$rootScope.$broadcast(‘incident.changed’, {});
}
Widget 2
Client Script
Widget 1
Client Script
© 2016 ServiceNow All Rights Reserved 45Confidential
45
#Know18
© 2018 ServiceNow All Rights Reserved
function ($scope) {
$scope.$on(‘incident.changed’,
function(event, data) {
// Do something!
});
}
function ($rootScope) {
$rootScope.$broadcast(‘incident.changed’, {});
}
Widget 2
Client Script
Widget 1
Client Script
© 2016 ServiceNow All Rights Reserved 46Confidential
46
#Know18
© 2018 ServiceNow All Rights Reserved
Embed
widgets to
compose
complex
behaviors
#1
Structure
application
models with
Angular
Services
#2
Use Angular
Events as a
last resort
#3
© 2016 ServiceNow All Rights Reserved 47Confidential
47
#Know18
© 2018 ServiceNow All Rights Reserved
© 2016 ServiceNow All Rights Reserved 48Confidential
48
#Know18
© 2018 ServiceNow All Rights Reserved
Travis Toulson
Sr. Architect
GlideFast Consulting
travis.toulson@glidefast.com
Thank You

More Related Content

PDF
Granada_Perl_Workshop_2014_Google_API_Client
PDF
Steam Learn: Asynchronous Javascript
PPTX
Lowering in C#: What really happens with your code?, from NDC Oslo 2019
PPTX
A (very) opinionated guide to MSBuild and Project Files
KEY
The Return of JavaScript: 3 Open-Source Projects that are driving JavaScript'...
PPT
Google Web Toolkit
PPT
Week 8
PDF
AppSync in real world - pitfalls, unexpected benefits & lessons learnt
Granada_Perl_Workshop_2014_Google_API_Client
Steam Learn: Asynchronous Javascript
Lowering in C#: What really happens with your code?, from NDC Oslo 2019
A (very) opinionated guide to MSBuild and Project Files
The Return of JavaScript: 3 Open-Source Projects that are driving JavaScript'...
Google Web Toolkit
Week 8
AppSync in real world - pitfalls, unexpected benefits & lessons learnt

Similar to Making Service Portal Widgets Work Together (20)

PDF
Chris Wilson: Progressive Web Apps
PDF
GlueCon 2016 - Threading in JavaScript
PPTX
Criteo Infrastructure (Platform) Meetup
PPTX
How to implement payment gateway integration for non-credit card on Magento2
PDF
The Future of Progressive Web Apps - Google for Indonesia
PPTX
InfluxDB 101 – Concepts and Architecture by Michael DeSa, Software Engineer |...
PDF
DataStax: 0 to App faster with Ruby and NodeJS
PDF
Server side rendering with React and Symfony
PPTX
Developing Business Blockchain Applications on Hyperledger
PDF
Building web APIs in PHP with Zend Expressive
PPTX
Learn How to Use a Time Series Platform to Monitor All Aspects of Your Kubern...
PDF
twMVC#46 一探 C# 11 與 .NET 7 的神奇
PDF
Urban Airship & Android Application Integration Document
PDF
Urban Airship and Android Integration for Push Notification and In-App Notifi...
PDF
Refatorando com a API funcional do Java
PPTX
Ingesting streaming data for analysis in apache ignite (stream sets theme)
PPTX
Ite express labs
PDF
A Journey with React
PDF
Preventing XSS with Content Security Policy
PPTX
PayPal Real Time Analytics
Chris Wilson: Progressive Web Apps
GlueCon 2016 - Threading in JavaScript
Criteo Infrastructure (Platform) Meetup
How to implement payment gateway integration for non-credit card on Magento2
The Future of Progressive Web Apps - Google for Indonesia
InfluxDB 101 – Concepts and Architecture by Michael DeSa, Software Engineer |...
DataStax: 0 to App faster with Ruby and NodeJS
Server side rendering with React and Symfony
Developing Business Blockchain Applications on Hyperledger
Building web APIs in PHP with Zend Expressive
Learn How to Use a Time Series Platform to Monitor All Aspects of Your Kubern...
twMVC#46 一探 C# 11 與 .NET 7 的神奇
Urban Airship & Android Application Integration Document
Urban Airship and Android Integration for Push Notification and In-App Notifi...
Refatorando com a API funcional do Java
Ingesting streaming data for analysis in apache ignite (stream sets theme)
Ite express labs
A Journey with React
Preventing XSS with Content Security Policy
PayPal Real Time Analytics
Ad

Recently uploaded (20)

PDF
Unlock new opportunities with location data.pdf
PPTX
observCloud-Native Containerability and monitoring.pptx
PPT
Module 1.ppt Iot fundamentals and Architecture
PDF
A review of recent deep learning applications in wood surface defect identifi...
PDF
How ambidextrous entrepreneurial leaders react to the artificial intelligence...
PPTX
Group 1 Presentation -Planning and Decision Making .pptx
PDF
A Late Bloomer's Guide to GenAI: Ethics, Bias, and Effective Prompting - Boha...
PPTX
The various Industrial Revolutions .pptx
PPT
What is a Computer? Input Devices /output devices
PPTX
Final SEM Unit 1 for mit wpu at pune .pptx
PDF
Hybrid horned lizard optimization algorithm-aquila optimizer for DC motor
PDF
DP Operators-handbook-extract for the Mautical Institute
PDF
DASA ADMISSION 2024_FirstRound_FirstRank_LastRank.pdf
PPTX
Modernising the Digital Integration Hub
PPT
Geologic Time for studying geology for geologist
PDF
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
PPTX
Chapter 5: Probability Theory and Statistics
PDF
Assigned Numbers - 2025 - Bluetooth® Document
PDF
ENT215_Completing-a-large-scale-migration-and-modernization-with-AWS.pdf
PDF
CloudStack 4.21: First Look Webinar slides
Unlock new opportunities with location data.pdf
observCloud-Native Containerability and monitoring.pptx
Module 1.ppt Iot fundamentals and Architecture
A review of recent deep learning applications in wood surface defect identifi...
How ambidextrous entrepreneurial leaders react to the artificial intelligence...
Group 1 Presentation -Planning and Decision Making .pptx
A Late Bloomer's Guide to GenAI: Ethics, Bias, and Effective Prompting - Boha...
The various Industrial Revolutions .pptx
What is a Computer? Input Devices /output devices
Final SEM Unit 1 for mit wpu at pune .pptx
Hybrid horned lizard optimization algorithm-aquila optimizer for DC motor
DP Operators-handbook-extract for the Mautical Institute
DASA ADMISSION 2024_FirstRound_FirstRank_LastRank.pdf
Modernising the Digital Integration Hub
Geologic Time for studying geology for geologist
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
Chapter 5: Probability Theory and Statistics
Assigned Numbers - 2025 - Bluetooth® Document
ENT215_Completing-a-large-scale-migration-and-modernization-with-AWS.pdf
CloudStack 4.21: First Look Webinar slides
Ad

Making Service Portal Widgets Work Together

  • 1. © 2018 ServiceNow All Rights Reserved Making Service Portal Widgets Work Together Travis Toulson Sr. Architect GlideFast Consulting
  • 2. © 2016 ServiceNow All Rights Reserved 2Confidential 2 #Know18 © 2018 ServiceNow All Rights Reserved Widgets are volatile, self-obsessed, and don’t play well with others Problem
  • 3. © 2016 ServiceNow All Rights Reserved 3Confidential 3 #Know18 © 2018 ServiceNow All Rights Reserved ng-app ng-controller container row column rectangle widget The Design Powerful widgets simplify everything else
  • 4. © 2016 ServiceNow All Rights Reserved 4Confidential 4 #Know18 © 2018 ServiceNow All Rights Reserved BUT…
  • 5. © 2016 ServiceNow All Rights Reserved 5Confidential 5 #Know18 © 2018 ServiceNow All Rights Reserved
  • 6. © 2016 ServiceNow All Rights Reserved 6Confidential 6 #Know18 © 2018 ServiceNow All Rights Reserved Massive Widgets Repetitive Widgets VS
  • 7. © 2016 ServiceNow All Rights Reserved 7Confidential 7 #Know18 © 2018 ServiceNow All Rights Reserved Embed widgets to compose complex behaviors #1
  • 8. © 2016 ServiceNow All Rights Reserved 8Confidential 8 #Know18 © 2018 ServiceNow All Rights Reserved ç Data Table Widget - 7 Different Behaviors - Over 300 lines of client code - Over 150 lines of server code
  • 9. © 2016 ServiceNow All Rights Reserved 9Confidential 9 #Know18 © 2018 ServiceNow All Rights Reserved <div> <sp-widget widget="data.filterBreadcrumbs"> </sp-widget> </div> var breadcrumbWidgetParams = { table: data.table, query: data.filter, enable_filter: data.enable_filter }; data.filterBreadcrumbs = $sp.getWidget( 'widget-filter-breadcrumbs', breadcrumbWidgetParams); HTML Server Script
  • 10. © 2016 ServiceNow All Rights Reserved 10Confidential 10 #Know18 © 2018 ServiceNow All Rights Reserved <div> <sp-widget widget="data.filterBreadcrumbs"> </sp-widget> </div> var breadcrumbWidgetParams = { table: data.table, query: data.filter, enable_filter: data.enable_filter }; data.filterBreadcrumbs = $sp.getWidget( 'widget-filter-breadcrumbs', breadcrumbWidgetParams); HTML Server Script
  • 11. © 2016 ServiceNow All Rights Reserved 11Confidential 11 #Know18 © 2018 ServiceNow All Rights Reserved <div> <sp-widget widget="data.filterBreadcrumbs"> </sp-widget> </div> var breadcrumbWidgetParams = { table: data.table, query: data.filter, enable_filter: data.enable_filter }; data.filterBreadcrumbs = $sp.getWidget( 'widget-filter-breadcrumbs', breadcrumbWidgetParams); HTML Server Script
  • 12. © 2016 ServiceNow All Rights Reserved 12Confidential 12 #Know18 © 2018 ServiceNow All Rights Reserved <div> <sp-widget widget="data.filterBreadcrumbs"> </sp-widget> </div> var breadcrumbWidgetParams = { table: data.table, query: data.filter, enable_filter: data.enable_filter }; data.filterBreadcrumbs = $sp.getWidget( 'widget-filter-breadcrumbs', breadcrumbWidgetParams); HTML Server Script
  • 13. © 2016 ServiceNow All Rights Reserved 13Confidential 13 #Know18 © 2018 ServiceNow All Rights Reserved <div> <sp-widget widget="data.filterBreadcrumbs"> </sp-widget> </div> var breadcrumbWidgetParams = { table: data.table, query: data.filter, enable_filter: data.enable_filter }; data.filterBreadcrumbs = $sp.getWidget( 'widget-filter-breadcrumbs', breadcrumbWidgetParams); HTML Server Script
  • 14. © 2016 ServiceNow All Rights Reserved 14Confidential 14 #Know18 © 2018 ServiceNow All Rights Reserved <div> <sp-widget widget="data.filterBreadcrumbs"> </sp-widget> </div> var breadcrumbWidgetParams = { table: data.table, query: data.filter, enable_filter: data.enable_filter }; data.filterBreadcrumbs = $sp.getWidget( 'widget-filter-breadcrumbs', breadcrumbWidgetParams); HTML Server Script
  • 15. © 2016 ServiceNow All Rights Reserved 15Confidential 15 #Know18 © 2018 ServiceNow All Rights Reserved A “child scope” (prototypically) inherits properties from its “parent scope” “ - AngularJS Developer Guide
  • 16. © 2016 ServiceNow All Rights Reserved 16Confidential 16 #Know18 © 2018 ServiceNow All Rights Reserved <a style="display: inline;" href>{{page.title}}</a> Data Table Widget HTML Template
  • 17. © 2016 ServiceNow All Rights Reserved 17Confidential 17 #Know18 © 2018 ServiceNow All Rights Reserved ng-app ng-controller container row column rectangle widget {{page.title}} Data Table Widget doesn’t have a page object?!?!
  • 18. © 2016 ServiceNow All Rights Reserved 18Confidential 18 #Know18 © 2018 ServiceNow All Rights Reserved Child Widgets inherit functions and data from their Parent Widgets
  • 19. © 2016 ServiceNow All Rights Reserved 19Confidential 19 #Know18 © 2018 ServiceNow All Rights Reserved Structure application models with Angular Services #2
  • 20. © 2016 ServiceNow All Rights Reserved 20Confidential 20 #Know18 © 2018 ServiceNow All Rights Reserved You can use services to organize and share code across your app “ - AngularJS Developer Guide
  • 21. © 2016 ServiceNow All Rights Reserved 21Confidential 21 #Know18 © 2018 ServiceNow All Rights Reserved 1. Create the Angular Provider 2. Add it to the Widget’s Angular Provider Related List 3. Inject the dependency into the Client Script Wire up a Service
  • 22. © 2016 ServiceNow All Rights Reserved 22Confidential 22 #Know18 © 2018 ServiceNow All Rights Reserved function($http) { var incidents = []; function reload() { $http.get(‘/api/now/table/incident’) .then(function(res) { incidents = res.result; }); } function get() { return incidents; } return { ‘reload’: reload, ‘get’: get }; } Service Type: Service Name: incidentService
  • 23. © 2016 ServiceNow All Rights Reserved 23Confidential 23 #Know18 © 2018 ServiceNow All Rights Reserved function($http) { var incidents = []; function reload() { $http.get(‘/api/now/table/incident’) .then(function(res) { incidents = res.result; }); } function get() { return incidents; } return { ‘reload’: reload, ‘get’: get }; } Service Type: Service Name: incidentService
  • 24. © 2016 ServiceNow All Rights Reserved 24Confidential 24 #Know18 © 2018 ServiceNow All Rights Reserved function($http) { var incidents = []; function reload() { $http.get(‘/api/now/table/incident’) .then(function(res) { incidents = res.result; }); } function get() { return incidents; } return { ‘reload’: reload, ‘get’: get }; } Service Type: Service Name: incidentService
  • 25. © 2016 ServiceNow All Rights Reserved 25Confidential 25 #Know18 © 2018 ServiceNow All Rights Reserved function($http) { var incidents = []; function reload() { $http.get(‘/api/now/table/incident’) .then(function(res) { incidents = res.result; }); } function get() { return incidents; } return { ‘reload’: reload, ‘get’: get }; } Service Type: Service Name: incidentService
  • 26. © 2016 ServiceNow All Rights Reserved 26Confidential 26 #Know18 © 2018 ServiceNow All Rights Reserved function($http) { var incidents = []; function reload() { $http.get(‘/api/now/table/incident’) .then(function(res) { incidents = res.result; }); } function get() { return incidents; } return { ‘reload’: reload, ‘get’: get }; } Service Type: Service Name: incidentService
  • 27. © 2016 ServiceNow All Rights Reserved 27Confidential 27 #Know18 © 2018 ServiceNow All Rights Reserved function($http) { var incidents = []; function reload() { $http.get(‘/api/now/table/incident’) .then(function(res) { incidents = res.result; }); } function get() { return incidents; } return { ‘reload’: reload, ‘get’: get }; } Service Type: Service Name: incidentService
  • 28. © 2016 ServiceNow All Rights Reserved 28Confidential 28 #Know18 © 2018 ServiceNow All Rights Reserved function (incidentService) { var c = this; incidentService.reload(); c.reload = function() { incidentService.reload(); } c.getIncidents = function() { return incidentService.get(); } } Client Script
  • 29. © 2016 ServiceNow All Rights Reserved 29Confidential 29 #Know18 © 2018 ServiceNow All Rights Reserved function (incidentService) { var c = this; incidentService.reload(); c.reload = function() { incidentService.reload(); } c.getIncidents = function() { return incidentService.get(); } } Client Script
  • 30. © 2016 ServiceNow All Rights Reserved 30Confidential 30 #Know18 © 2018 ServiceNow All Rights Reserved function (incidentService) { var c = this; incidentService.reload(); c.reload = function() { incidentService.reload(); } c.getIncidents = function() { return incidentService.get(); } } Client Script
  • 31. © 2016 ServiceNow All Rights Reserved 31Confidential 31 #Know18 © 2018 ServiceNow All Rights Reserved function (incidentService) { var c = this; incidentService.reload(); c.reload = function() { incidentService.reload(); } c.getIncidents = function() { return incidentService.get(); } } Client Script
  • 32. © 2016 ServiceNow All Rights Reserved 32Confidential 32 #Know18 © 2018 ServiceNow All Rights Reserved function (incidentService) { var c = this; incidentService.reload(); c.reload = function() { incidentService.reload(); } c.getIncidents = function() { return incidentService.get(); } } Client Script
  • 33. © 2016 ServiceNow All Rights Reserved 33Confidential 33 #Know18 © 2018 ServiceNow All Rights Reserved <div ng-repeat=“inc in c.getIncidents()”> <!-- Incident Template Here --> </div> Digest Loop HTML Template
  • 34. © 2016 ServiceNow All Rights Reserved 34Confidential 34 #Know18 © 2018 ServiceNow All Rights Reserved Use Angular Events as a last resort #3
  • 35. © 2016 ServiceNow All Rights Reserved 35Confidential 35 #Know18 © 2018 ServiceNow All Rights Reserved Insanity Warning: scope depth- first traversal. Yes, this code is a bit crazy, but it works and we have tests to prove it “ - Line 1417, rootScope.js AngularJS Source Code
  • 36. © 2016 ServiceNow All Rights Reserved 36Confidential 36 #Know18 © 2018 ServiceNow All Rights Reserved ng-app ng-controller container row column rectangle widget Event Propagation $rootScope $scope $broadcast $emit $on
  • 37. © 2016 ServiceNow All Rights Reserved 37Confidential 37 #Know18 © 2018 ServiceNow All Rights Reserved But given that it’s a stupid a** decision, I’ve elected to ignore it
  • 38. © 2016 ServiceNow All Rights Reserved 38Confidential 38 #Know18 © 2018 ServiceNow All Rights Reserved function ($scope) { $scope.$on(‘incident.changed’, function(event, data) { // Do something! }); } function ($rootScope) { $rootScope.$broadcast(‘incident.changed’, {}); } Widget 2 Client Script Widget 1 Client Script
  • 39. © 2016 ServiceNow All Rights Reserved 39Confidential 39 #Know18 © 2018 ServiceNow All Rights Reserved function ($scope) { $scope.$on(‘incident.changed’, function(event, data) { // Do something! }); } function ($rootScope) { $rootScope.$broadcast(‘incident.changed’, {}); } Widget 2 Client Script Widget 1 Client Script
  • 40. © 2016 ServiceNow All Rights Reserved 40Confidential 40 #Know18 © 2018 ServiceNow All Rights Reserved function ($scope) { $scope.$on(‘incident.changed’, function(event, data) { // Do something! }); } function ($rootScope) { $rootScope.$broadcast(‘incident.changed’, {}); } Widget 2 Client Script Widget 1 Client Script
  • 41. © 2016 ServiceNow All Rights Reserved 41Confidential 41 #Know18 © 2018 ServiceNow All Rights Reserved function ($scope) { $scope.$on(‘incident.changed’, function(event, data) { // Do something! }); } function ($rootScope) { $rootScope.$broadcast(‘incident.changed’, {}); } Widget 2 Client Script Widget 1 Client Script
  • 42. © 2016 ServiceNow All Rights Reserved 42Confidential 42 #Know18 © 2018 ServiceNow All Rights Reserved function ($scope) { $scope.$on(‘incident.changed’, function(event, data) { // Do something! }); } function ($rootScope) { $rootScope.$broadcast(‘incident.changed’, {}); } Widget 2 Client Script Widget 1 Client Script
  • 43. © 2016 ServiceNow All Rights Reserved 43Confidential 43 #Know18 © 2018 ServiceNow All Rights Reserved function ($scope) { $scope.$on(‘incident.changed’, function(event, data) { // Do something! }); } function ($rootScope) { $rootScope.$broadcast(‘incident.changed’, {}); } Widget 2 Client Script Widget 1 Client Script
  • 44. © 2016 ServiceNow All Rights Reserved 44Confidential 44 #Know18 © 2018 ServiceNow All Rights Reserved function ($scope) { $scope.$on(‘incident.changed’, function(event, data) { // Do something! }); } function ($rootScope) { $rootScope.$broadcast(‘incident.changed’, {}); } Widget 2 Client Script Widget 1 Client Script
  • 45. © 2016 ServiceNow All Rights Reserved 45Confidential 45 #Know18 © 2018 ServiceNow All Rights Reserved function ($scope) { $scope.$on(‘incident.changed’, function(event, data) { // Do something! }); } function ($rootScope) { $rootScope.$broadcast(‘incident.changed’, {}); } Widget 2 Client Script Widget 1 Client Script
  • 46. © 2016 ServiceNow All Rights Reserved 46Confidential 46 #Know18 © 2018 ServiceNow All Rights Reserved Embed widgets to compose complex behaviors #1 Structure application models with Angular Services #2 Use Angular Events as a last resort #3
  • 47. © 2016 ServiceNow All Rights Reserved 47Confidential 47 #Know18 © 2018 ServiceNow All Rights Reserved
  • 48. © 2016 ServiceNow All Rights Reserved 48Confidential 48 #Know18 © 2018 ServiceNow All Rights Reserved Travis Toulson Sr. Architect GlideFast Consulting travis.toulson@glidefast.com Thank You