53. But wait, how do we pass data between
directives?
Navigation
Workspace
Actions
Menu
e.g. How does the Navigation directive find out about a
selection in the Menu directive?
#smartorgdev 24
54. But wait, how do we pass data between
directives?
Navigation
Workspace
Actions
Menu
e.g. list of trees
e.g. How does the Navigation directive find out which
tree has been selected in the Menu directive?
#smartorgdev 25
68. Legacy Application
Non-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke “widgets”
using directives
!
#smartorgdev 29
71. In your legacy web application, render this html:
<div id="mywidgetOuterDiv">!
<div id="mywidget" class="" ng-controller="MyWidgetCtrl">!
<div mywidget-directive!
input-data="inputData" !
setup-data="setupData()">!
</div> !
</div>!
</div>!
!
and this JS:
jsCode = "APP.myWidgetConfig = { inputData: {…} }"!
In your JS code, bootstrap your widget:
angular.bootstrap($('#mywidgetOuterDiv'), ['myApp']);!
var scope = $('#mywidget').scope();!
scope.setupData(APP.myWidgetConfig);!
!
31
72. In your legacy web application, render this html:
<div id="mywidgetOuterDiv">!
<div id="mywidget" class="" ng-controller="MyWidgetCtrl">!
<div mywidget-directive!
input-data="inputData" !
setup-data="setupData()">!
</div> !
</div>!
</div>!
!
widget
directive
and this JS:
jsCode = "APP.myWidgetConfig = { inputData: {…} }"!
In your JS code, bootstrap your widget:
angular.bootstrap($('#mywidgetOuterDiv'), ['myApp']);!
var scope = $('#mywidget').scope();!
scope.setupData(APP.myWidgetConfig);!
!
31
73. In your legacy web application, render this html:
<div id="mywidgetOuterDiv">!
<div id="mywidget" class="" ng-controller="MyWidgetCtrl">!
<div mywidget-directive!
input-data="inputData" !
setup-data="setupData()">!
</div> !
</div>!
</div>!
!
widget
directive
In your JS code, bootstrap your widget:
angular.bootstrap($('#mywidgetOuterDiv'), ['myApp']);!
var scope = $('#mywidget').scope();!
scope.setupData(APP.myWidgetConfig);!
!
widget
controller
and this JS:
jsCode = "APP.myWidgetConfig = { inputData: {…} }"!
31
74. In your legacy web application, render this html:
<div id="mywidgetOuterDiv">!
<div id="mywidget" class="" ng-controller="MyWidgetCtrl">!
<div mywidget-directive!
input-data="inputData" !
setup-data="setupData()">!
</div> !
</div>!
</div>!
!
widget
directive
In your JS code, bootstrap your widget:
angular.bootstrap($('#mywidgetOuterDiv'), ['myApp']);!
var scope = $('#mywidget').scope();!
scope.setupData(APP.myWidgetConfig);!
!
widget
controller
widget
container
and this JS:
jsCode = "APP.myWidgetConfig = { inputData: {…} }"!
31
75. In your legacy web application, render this html:
<div id="mywidgetOuterDiv">!
<div id="mywidget" class="" ng-controller="MyWidgetCtrl">!
<div mywidget-directive!
input-data="inputData" !
setup-data="setupData()">!
</div> !
</div>!
</div>!
!
widget
directive
In your JS code, bootstrap your widget:
angular.bootstrap($('#mywidgetOuterDiv'), ['myApp']);!
var scope = $('#mywidget').scope();!
scope.setupData(APP.myWidgetConfig);!
!
widget
controller
widget
container
and this JS:
jsCode = "APP.myWidgetConfig = { inputData: {…} }"!
31
76. In your legacy web application, render this html:
<div id="mywidgetOuterDiv">!
<div id="mywidget" class="" ng-controller="MyWidgetCtrl">!
<div mywidget-directive!
input-data="inputData" !
setup-data="setupData()">!
</div> !
</div>!
</div>!
!
widget
directive
In your JS code, bootstrap your widget:
angular.bootstrap($('#mywidgetOuterDiv'), ['myApp']);!
var scope = $('#mywidget').scope();!
scope.setupData(APP.myWidgetConfig);!
!
widget
controller
widget
container
and this JS:
jsCode = "APP.myWidgetConfig = { inputData: {…} }"!
31
77. In your legacy web application, render this html:
<div id="mywidgetOuterDiv">!
<div id="mywidget" class="" ng-controller="MyWidgetCtrl">!
<div mywidget-directive!
input-data="inputData" !
setup-data="setupData()">!
</div> !
</div>!
</div>!
!
widget
directive
In your JS code, bootstrap your widget:
angular.bootstrap($('#mywidgetOuterDiv'), ['myApp']);!
var scope = $('#mywidget').scope();!
scope.setupData(APP.myWidgetConfig);!
!
widget
controller
widget
container
and this JS:
jsCode = "APP.myWidgetConfig = { inputData: {…} }"!
31
78. In your legacy web application, render this html:
<div id="mywidgetOuterDiv">!
<div id="mywidget" class="" ng-controller="MyWidgetCtrl">!
<div mywidget-directive!
input-data="inputData" !
setup-data="setupData()">!
</div> !
</div>!
</div>!
!
widget
directive
In your JS code, bootstrap your widget:
angular.bootstrap($('#mywidgetOuterDiv'), ['myApp']);!
var scope = $('#mywidget').scope();!
scope.setupData(APP.myWidgetConfig);!
!
widget
controller
widget
container
and this JS:
jsCode = "APP.myWidgetConfig = { inputData: {…} }"!
Pattern: !
Dynamically invoke angular application
31
79. angular.module('myApp')!
.controller('MyWidgetCtrl', function($scope) {!
$scope.setupData = function(myWidgetConfig:MyWidgetConfig) {!
if (!$scope.inputData && !myWidgetConfig) {!
addTablesConfig = window.standalone.myWidgetConfig;!
} else if ($scope.inputData && !myWidgetConfig) {!
return;!
}!
$scope.inputData = myWidgetConfig.inputData;!
};!
})!
.directive('mywidgetDirective', function() {!
var templateUrl = '/path/to/template.html';!
if (!window.production) {!
templateUrl = 'localpath/to/template.html'!
}!
return {!
restrict: 'A',!
templateUrl: templateUrl,!
scope: {!
inputData: '=',!
setupData: '&'!
},!
link: function (scope, elem, attrs, ctrl) {!
}!
}!
});!
!
Data made available to
directive scope
standalone.js
32
80. angular.module('myApp')!
.controller('MyWidgetCtrl', function($scope) {!
$scope.setupData = function(myWidgetConfig:MyWidgetConfig) {!
if (!$scope.inputData && !myWidgetConfig) {!
addTablesConfig = window.standalone.myWidgetConfig;!
} else if ($scope.inputData && !myWidgetConfig) {!
return;!
}!
$scope.inputData = myWidgetConfig.inputData;!
};!
})!
.directive('mywidgetDirective', function() {!
var templateUrl = '/path/to/template.html';!
if (!window.production) {!
templateUrl = 'localpath/to/template.html'!
}!
return {!
restrict: 'A',!
templateUrl: templateUrl,!
scope: {!
inputData: '=',!
setupData: '&'!
},!
link: function (scope, elem, attrs, ctrl) {!
}!
}!
});!
!
Data made available to
directive scope
standalone.js
32
81. angular.module('myApp')!
.controller('MyWidgetCtrl', function($scope) {!
$scope.setupData = function(myWidgetConfig:MyWidgetConfig) {!
if (!$scope.inputData && !myWidgetConfig) {!
addTablesConfig = window.standalone.myWidgetConfig;!
} else if ($scope.inputData && !myWidgetConfig) {!
return;!
}!
$scope.inputData = myWidgetConfig.inputData;!
};!
})!
.directive('mywidgetDirective', function() {!
var templateUrl = '/path/to/template.html';!
if (!window.production) {!
templateUrl = 'localpath/to/template.html'!
}!
return {!
restrict: 'A',!
templateUrl: templateUrl,!
scope: {!
inputData: '=',!
setupData: '&'!
},!
link: function (scope, elem, attrs, ctrl) {!
}!
}!
});!
!
Data made available to
directive scope
standalone.js
32
82. angular.module('myApp')!
.controller('MyWidgetCtrl', function($scope) {!
$scope.setupData = function(myWidgetConfig:MyWidgetConfig) {!
if (!$scope.inputData && !myWidgetConfig) {!
addTablesConfig = window.standalone.myWidgetConfig;!
} else if ($scope.inputData && !myWidgetConfig) {!
return;!
}!
$scope.inputData = myWidgetConfig.inputData;!
};!
})!
.directive('mywidgetDirective', function() {!
var templateUrl = '/path/to/template.html';!
if (!window.production) {!
Allows for standalone
templateUrl = 'localpath/to/template.html'!
}!
return {!
restrict: 'A',!
templateUrl: templateUrl,!
scope: {!
inputData: '=',!
setupData: '&'!
},!
link: function (scope, elem, attrs, ctrl) {!
}!
}!
});!
!
Data made available to
directive scope
standalone.js
32
widget testing
window.standalone = {!
myWidgetConfig: {!
inputData: …!
}!
}!
!
standalone index.html
83. angular.module('myApp')!
.controller('MyWidgetCtrl', function($scope) {!
$scope.setupData = function(myWidgetConfig:MyWidgetConfig) {!
if (!$scope.inputData && !myWidgetConfig) {!
addTablesConfig = window.standalone.myWidgetConfig;!
} else if ($scope.inputData && !myWidgetConfig) {!
return;!
}!
$scope.inputData = myWidgetConfig.inputData;!
};!
})!
.directive('mywidgetDirective', function() {!
var templateUrl = '/path/to/template.html';!
if (!window.production) {!
Allows for standalone
templateUrl = 'localpath/to/template.html'!
}!
return {!
restrict: 'A',!
templateUrl: templateUrl,!
scope: {!
inputData: '=',!
setupData: '&'!
},!
link: function (scope, elem, attrs, ctrl) {!
}!
}!
});!
!
Data made available to
directive scope
standalone.js
Pattern: !
Standalone Widget Mode
32
widget testing
window.standalone = {!
myWidgetConfig: {!
inputData: …!
}!
}!
!
standalone index.html
84. Testing notes
Avoid putting business logic in controllers
!
Put them in Typescript classes that can be independently
tested
!
Use HttpMocks to ensure controllers work fine
#smartorgdev 33
85. Old ideas like modularity, once-and-only-once,
etc. still apply
!
They just look different
#smartorgdev 34