Download - Design strategies for AngularJS
Design Strategies with AngularJS
1
Design Strategies with AngularJS
1
Somik Raha
Design Strategies with AngularJS
1
Somik Raha Kai Wu
Design Strategies with AngularJS
1
smartorgdevSomik Raha Kai Wu
Rip Van Winkle
Slept through the American
Revolution
Slept off in 2004 and woke up in
2014 2
3
2004hellip
3
2004hellip
3
2004hellip
C++
3
2004hellip
C++ Java
3
2004hellip
C++ JavaMicrosoft
3
2004hellip
C++ JavaSunMicrosoft
3
2004hellip
C++ JavaSunMicrosoft
3smartorgdev
2014
C++ JavaSunMicrosoft
4smartorgdev
2014
Javascript4smartorgdev
Backend
5smartorgdev
Backend Middleware
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
6smartorgdev
Super-heroic Javascript framework
7smartorgdev
Super-heroic Javascript framework
7smartorgdev
First reaction
I donrsquot get it Backbone is great for us
8smartorgdev
Second reaction
Whoa
9smartorgdev
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10
Staircase
Controllers and views
Directives
Servicehellip
10
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10Ben Nadelrsquos blog
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Three Kinds of Scenarios
Single Page Application
Multi-Page Application
Legacy Application
Classic Sophisticated Convoluted
12smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
Design Strategies with AngularJS
1
Somik Raha
Design Strategies with AngularJS
1
Somik Raha Kai Wu
Design Strategies with AngularJS
1
smartorgdevSomik Raha Kai Wu
Rip Van Winkle
Slept through the American
Revolution
Slept off in 2004 and woke up in
2014 2
3
2004hellip
3
2004hellip
3
2004hellip
C++
3
2004hellip
C++ Java
3
2004hellip
C++ JavaMicrosoft
3
2004hellip
C++ JavaSunMicrosoft
3
2004hellip
C++ JavaSunMicrosoft
3smartorgdev
2014
C++ JavaSunMicrosoft
4smartorgdev
2014
Javascript4smartorgdev
Backend
5smartorgdev
Backend Middleware
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
6smartorgdev
Super-heroic Javascript framework
7smartorgdev
Super-heroic Javascript framework
7smartorgdev
First reaction
I donrsquot get it Backbone is great for us
8smartorgdev
Second reaction
Whoa
9smartorgdev
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10
Staircase
Controllers and views
Directives
Servicehellip
10
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10Ben Nadelrsquos blog
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Three Kinds of Scenarios
Single Page Application
Multi-Page Application
Legacy Application
Classic Sophisticated Convoluted
12smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
Design Strategies with AngularJS
1
Somik Raha Kai Wu
Design Strategies with AngularJS
1
smartorgdevSomik Raha Kai Wu
Rip Van Winkle
Slept through the American
Revolution
Slept off in 2004 and woke up in
2014 2
3
2004hellip
3
2004hellip
3
2004hellip
C++
3
2004hellip
C++ Java
3
2004hellip
C++ JavaMicrosoft
3
2004hellip
C++ JavaSunMicrosoft
3
2004hellip
C++ JavaSunMicrosoft
3smartorgdev
2014
C++ JavaSunMicrosoft
4smartorgdev
2014
Javascript4smartorgdev
Backend
5smartorgdev
Backend Middleware
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
6smartorgdev
Super-heroic Javascript framework
7smartorgdev
Super-heroic Javascript framework
7smartorgdev
First reaction
I donrsquot get it Backbone is great for us
8smartorgdev
Second reaction
Whoa
9smartorgdev
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10
Staircase
Controllers and views
Directives
Servicehellip
10
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10Ben Nadelrsquos blog
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Three Kinds of Scenarios
Single Page Application
Multi-Page Application
Legacy Application
Classic Sophisticated Convoluted
12smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
Design Strategies with AngularJS
1
smartorgdevSomik Raha Kai Wu
Rip Van Winkle
Slept through the American
Revolution
Slept off in 2004 and woke up in
2014 2
3
2004hellip
3
2004hellip
3
2004hellip
C++
3
2004hellip
C++ Java
3
2004hellip
C++ JavaMicrosoft
3
2004hellip
C++ JavaSunMicrosoft
3
2004hellip
C++ JavaSunMicrosoft
3smartorgdev
2014
C++ JavaSunMicrosoft
4smartorgdev
2014
Javascript4smartorgdev
Backend
5smartorgdev
Backend Middleware
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
6smartorgdev
Super-heroic Javascript framework
7smartorgdev
Super-heroic Javascript framework
7smartorgdev
First reaction
I donrsquot get it Backbone is great for us
8smartorgdev
Second reaction
Whoa
9smartorgdev
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10
Staircase
Controllers and views
Directives
Servicehellip
10
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10Ben Nadelrsquos blog
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Three Kinds of Scenarios
Single Page Application
Multi-Page Application
Legacy Application
Classic Sophisticated Convoluted
12smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
Rip Van Winkle
Slept through the American
Revolution
Slept off in 2004 and woke up in
2014 2
3
2004hellip
3
2004hellip
3
2004hellip
C++
3
2004hellip
C++ Java
3
2004hellip
C++ JavaMicrosoft
3
2004hellip
C++ JavaSunMicrosoft
3
2004hellip
C++ JavaSunMicrosoft
3smartorgdev
2014
C++ JavaSunMicrosoft
4smartorgdev
2014
Javascript4smartorgdev
Backend
5smartorgdev
Backend Middleware
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
6smartorgdev
Super-heroic Javascript framework
7smartorgdev
Super-heroic Javascript framework
7smartorgdev
First reaction
I donrsquot get it Backbone is great for us
8smartorgdev
Second reaction
Whoa
9smartorgdev
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10
Staircase
Controllers and views
Directives
Servicehellip
10
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10Ben Nadelrsquos blog
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Three Kinds of Scenarios
Single Page Application
Multi-Page Application
Legacy Application
Classic Sophisticated Convoluted
12smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
3
2004hellip
3
2004hellip
3
2004hellip
C++
3
2004hellip
C++ Java
3
2004hellip
C++ JavaMicrosoft
3
2004hellip
C++ JavaSunMicrosoft
3
2004hellip
C++ JavaSunMicrosoft
3smartorgdev
2014
C++ JavaSunMicrosoft
4smartorgdev
2014
Javascript4smartorgdev
Backend
5smartorgdev
Backend Middleware
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
6smartorgdev
Super-heroic Javascript framework
7smartorgdev
Super-heroic Javascript framework
7smartorgdev
First reaction
I donrsquot get it Backbone is great for us
8smartorgdev
Second reaction
Whoa
9smartorgdev
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10
Staircase
Controllers and views
Directives
Servicehellip
10
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10Ben Nadelrsquos blog
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Three Kinds of Scenarios
Single Page Application
Multi-Page Application
Legacy Application
Classic Sophisticated Convoluted
12smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
2004hellip
3
2004hellip
3
2004hellip
C++
3
2004hellip
C++ Java
3
2004hellip
C++ JavaMicrosoft
3
2004hellip
C++ JavaSunMicrosoft
3
2004hellip
C++ JavaSunMicrosoft
3smartorgdev
2014
C++ JavaSunMicrosoft
4smartorgdev
2014
Javascript4smartorgdev
Backend
5smartorgdev
Backend Middleware
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
6smartorgdev
Super-heroic Javascript framework
7smartorgdev
Super-heroic Javascript framework
7smartorgdev
First reaction
I donrsquot get it Backbone is great for us
8smartorgdev
Second reaction
Whoa
9smartorgdev
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10
Staircase
Controllers and views
Directives
Servicehellip
10
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10Ben Nadelrsquos blog
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Three Kinds of Scenarios
Single Page Application
Multi-Page Application
Legacy Application
Classic Sophisticated Convoluted
12smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
2004hellip
3
2004hellip
C++
3
2004hellip
C++ Java
3
2004hellip
C++ JavaMicrosoft
3
2004hellip
C++ JavaSunMicrosoft
3
2004hellip
C++ JavaSunMicrosoft
3smartorgdev
2014
C++ JavaSunMicrosoft
4smartorgdev
2014
Javascript4smartorgdev
Backend
5smartorgdev
Backend Middleware
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
6smartorgdev
Super-heroic Javascript framework
7smartorgdev
Super-heroic Javascript framework
7smartorgdev
First reaction
I donrsquot get it Backbone is great for us
8smartorgdev
Second reaction
Whoa
9smartorgdev
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10
Staircase
Controllers and views
Directives
Servicehellip
10
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10Ben Nadelrsquos blog
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Three Kinds of Scenarios
Single Page Application
Multi-Page Application
Legacy Application
Classic Sophisticated Convoluted
12smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
2004hellip
C++
3
2004hellip
C++ Java
3
2004hellip
C++ JavaMicrosoft
3
2004hellip
C++ JavaSunMicrosoft
3
2004hellip
C++ JavaSunMicrosoft
3smartorgdev
2014
C++ JavaSunMicrosoft
4smartorgdev
2014
Javascript4smartorgdev
Backend
5smartorgdev
Backend Middleware
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
6smartorgdev
Super-heroic Javascript framework
7smartorgdev
Super-heroic Javascript framework
7smartorgdev
First reaction
I donrsquot get it Backbone is great for us
8smartorgdev
Second reaction
Whoa
9smartorgdev
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10
Staircase
Controllers and views
Directives
Servicehellip
10
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10Ben Nadelrsquos blog
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Three Kinds of Scenarios
Single Page Application
Multi-Page Application
Legacy Application
Classic Sophisticated Convoluted
12smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
2004hellip
C++ Java
3
2004hellip
C++ JavaMicrosoft
3
2004hellip
C++ JavaSunMicrosoft
3
2004hellip
C++ JavaSunMicrosoft
3smartorgdev
2014
C++ JavaSunMicrosoft
4smartorgdev
2014
Javascript4smartorgdev
Backend
5smartorgdev
Backend Middleware
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
6smartorgdev
Super-heroic Javascript framework
7smartorgdev
Super-heroic Javascript framework
7smartorgdev
First reaction
I donrsquot get it Backbone is great for us
8smartorgdev
Second reaction
Whoa
9smartorgdev
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10
Staircase
Controllers and views
Directives
Servicehellip
10
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10Ben Nadelrsquos blog
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Three Kinds of Scenarios
Single Page Application
Multi-Page Application
Legacy Application
Classic Sophisticated Convoluted
12smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
2004hellip
C++ JavaMicrosoft
3
2004hellip
C++ JavaSunMicrosoft
3
2004hellip
C++ JavaSunMicrosoft
3smartorgdev
2014
C++ JavaSunMicrosoft
4smartorgdev
2014
Javascript4smartorgdev
Backend
5smartorgdev
Backend Middleware
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
6smartorgdev
Super-heroic Javascript framework
7smartorgdev
Super-heroic Javascript framework
7smartorgdev
First reaction
I donrsquot get it Backbone is great for us
8smartorgdev
Second reaction
Whoa
9smartorgdev
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10
Staircase
Controllers and views
Directives
Servicehellip
10
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10Ben Nadelrsquos blog
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Three Kinds of Scenarios
Single Page Application
Multi-Page Application
Legacy Application
Classic Sophisticated Convoluted
12smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
2004hellip
C++ JavaSunMicrosoft
3
2004hellip
C++ JavaSunMicrosoft
3smartorgdev
2014
C++ JavaSunMicrosoft
4smartorgdev
2014
Javascript4smartorgdev
Backend
5smartorgdev
Backend Middleware
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
6smartorgdev
Super-heroic Javascript framework
7smartorgdev
Super-heroic Javascript framework
7smartorgdev
First reaction
I donrsquot get it Backbone is great for us
8smartorgdev
Second reaction
Whoa
9smartorgdev
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10
Staircase
Controllers and views
Directives
Servicehellip
10
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10Ben Nadelrsquos blog
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Three Kinds of Scenarios
Single Page Application
Multi-Page Application
Legacy Application
Classic Sophisticated Convoluted
12smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
2004hellip
C++ JavaSunMicrosoft
3smartorgdev
2014
C++ JavaSunMicrosoft
4smartorgdev
2014
Javascript4smartorgdev
Backend
5smartorgdev
Backend Middleware
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
6smartorgdev
Super-heroic Javascript framework
7smartorgdev
Super-heroic Javascript framework
7smartorgdev
First reaction
I donrsquot get it Backbone is great for us
8smartorgdev
Second reaction
Whoa
9smartorgdev
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10
Staircase
Controllers and views
Directives
Servicehellip
10
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10Ben Nadelrsquos blog
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Three Kinds of Scenarios
Single Page Application
Multi-Page Application
Legacy Application
Classic Sophisticated Convoluted
12smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
2014
C++ JavaSunMicrosoft
4smartorgdev
2014
Javascript4smartorgdev
Backend
5smartorgdev
Backend Middleware
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
6smartorgdev
Super-heroic Javascript framework
7smartorgdev
Super-heroic Javascript framework
7smartorgdev
First reaction
I donrsquot get it Backbone is great for us
8smartorgdev
Second reaction
Whoa
9smartorgdev
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10
Staircase
Controllers and views
Directives
Servicehellip
10
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10Ben Nadelrsquos blog
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Three Kinds of Scenarios
Single Page Application
Multi-Page Application
Legacy Application
Classic Sophisticated Convoluted
12smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
2014
Javascript4smartorgdev
Backend
5smartorgdev
Backend Middleware
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
6smartorgdev
Super-heroic Javascript framework
7smartorgdev
Super-heroic Javascript framework
7smartorgdev
First reaction
I donrsquot get it Backbone is great for us
8smartorgdev
Second reaction
Whoa
9smartorgdev
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10
Staircase
Controllers and views
Directives
Servicehellip
10
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10Ben Nadelrsquos blog
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Three Kinds of Scenarios
Single Page Application
Multi-Page Application
Legacy Application
Classic Sophisticated Convoluted
12smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
Backend
5smartorgdev
Backend Middleware
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
6smartorgdev
Super-heroic Javascript framework
7smartorgdev
Super-heroic Javascript framework
7smartorgdev
First reaction
I donrsquot get it Backbone is great for us
8smartorgdev
Second reaction
Whoa
9smartorgdev
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10
Staircase
Controllers and views
Directives
Servicehellip
10
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10Ben Nadelrsquos blog
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Three Kinds of Scenarios
Single Page Application
Multi-Page Application
Legacy Application
Classic Sophisticated Convoluted
12smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
Backend Middleware
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
6smartorgdev
Super-heroic Javascript framework
7smartorgdev
Super-heroic Javascript framework
7smartorgdev
First reaction
I donrsquot get it Backbone is great for us
8smartorgdev
Second reaction
Whoa
9smartorgdev
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10
Staircase
Controllers and views
Directives
Servicehellip
10
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10Ben Nadelrsquos blog
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Three Kinds of Scenarios
Single Page Application
Multi-Page Application
Legacy Application
Classic Sophisticated Convoluted
12smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
6smartorgdev
Super-heroic Javascript framework
7smartorgdev
Super-heroic Javascript framework
7smartorgdev
First reaction
I donrsquot get it Backbone is great for us
8smartorgdev
Second reaction
Whoa
9smartorgdev
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10
Staircase
Controllers and views
Directives
Servicehellip
10
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10Ben Nadelrsquos blog
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Three Kinds of Scenarios
Single Page Application
Multi-Page Application
Legacy Application
Classic Sophisticated Convoluted
12smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
Backend Middleware Front-end
5smartorgdev
Backend Middleware Front-end
6smartorgdev
Super-heroic Javascript framework
7smartorgdev
Super-heroic Javascript framework
7smartorgdev
First reaction
I donrsquot get it Backbone is great for us
8smartorgdev
Second reaction
Whoa
9smartorgdev
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10
Staircase
Controllers and views
Directives
Servicehellip
10
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10Ben Nadelrsquos blog
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Three Kinds of Scenarios
Single Page Application
Multi-Page Application
Legacy Application
Classic Sophisticated Convoluted
12smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
Backend Middleware Front-end
6smartorgdev
Super-heroic Javascript framework
7smartorgdev
Super-heroic Javascript framework
7smartorgdev
First reaction
I donrsquot get it Backbone is great for us
8smartorgdev
Second reaction
Whoa
9smartorgdev
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10
Staircase
Controllers and views
Directives
Servicehellip
10
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10Ben Nadelrsquos blog
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Three Kinds of Scenarios
Single Page Application
Multi-Page Application
Legacy Application
Classic Sophisticated Convoluted
12smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
Super-heroic Javascript framework
7smartorgdev
Super-heroic Javascript framework
7smartorgdev
First reaction
I donrsquot get it Backbone is great for us
8smartorgdev
Second reaction
Whoa
9smartorgdev
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10
Staircase
Controllers and views
Directives
Servicehellip
10
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10Ben Nadelrsquos blog
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Three Kinds of Scenarios
Single Page Application
Multi-Page Application
Legacy Application
Classic Sophisticated Convoluted
12smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
Super-heroic Javascript framework
7smartorgdev
First reaction
I donrsquot get it Backbone is great for us
8smartorgdev
Second reaction
Whoa
9smartorgdev
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10
Staircase
Controllers and views
Directives
Servicehellip
10
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10Ben Nadelrsquos blog
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Three Kinds of Scenarios
Single Page Application
Multi-Page Application
Legacy Application
Classic Sophisticated Convoluted
12smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
First reaction
I donrsquot get it Backbone is great for us
8smartorgdev
Second reaction
Whoa
9smartorgdev
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10
Staircase
Controllers and views
Directives
Servicehellip
10
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10Ben Nadelrsquos blog
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Three Kinds of Scenarios
Single Page Application
Multi-Page Application
Legacy Application
Classic Sophisticated Convoluted
12smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
Second reaction
Whoa
9smartorgdev
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10
Staircase
Controllers and views
Directives
Servicehellip
10
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10Ben Nadelrsquos blog
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Three Kinds of Scenarios
Single Page Application
Multi-Page Application
Legacy Application
Classic Sophisticated Convoluted
12smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10
Staircase
Controllers and views
Directives
Servicehellip
10
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10Ben Nadelrsquos blog
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Three Kinds of Scenarios
Single Page Application
Multi-Page Application
Legacy Application
Classic Sophisticated Convoluted
12smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
Backbone learning curve AngularJS learning curve
Flattens quicklyMinimal concepts
10Ben Nadelrsquos blog
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Three Kinds of Scenarios
Single Page Application
Multi-Page Application
Legacy Application
Classic Sophisticated Convoluted
12smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Three Kinds of Scenarios
Single Page Application
Multi-Page Application
Legacy Application
Classic Sophisticated Convoluted
12smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Three Kinds of Scenarios
Single Page Application
Multi-Page Application
Legacy Application
Classic Sophisticated Convoluted
12smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
Stats comparing Backbone with AngularJS
AppStructure Wizard
11smartorgdev
Three Kinds of Scenarios
Single Page Application
Multi-Page Application
Legacy Application
Classic Sophisticated Convoluted
12smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
Three Kinds of Scenarios
Single Page Application
Multi-Page Application
Legacy Application
Classic Sophisticated Convoluted
12smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
Multi-Page Application
Map routes to controllers and views
Page 1 Page 2 Page 3
eg Logineg Show Projects
View 1 View 2 View 3
Controller 1 Controller 2 Controller 3
Route 1 Route 2 Route 3login showProjects hellip
Browser loads entire page
13smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(route1 13 controller Controller1 as c113 templateUrl viewsview1html13 )when(route2 13 controller Controller2 as c213 templateUrl viewsview2html13 )otherwise(13 redirectTo route113 )13)13
Route1
View1
Controller1
Route2
View2
Controller2
Map routes to controllers and viewsappjs
14
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
angularmodule(myApp [13 ngRoute13 hellip13])config(function ($routeProvider) 13 $routeProviderwhen(showProjects 13 controller ShowProjectsController as show13 templateUrl lsquoviewsshowProjectshtmlrsquo13 )when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )otherwise(13 redirectTo login13 )13)13
Routeshttplogin
httpshowProjectsappjs
15
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
Routeshttplogin
httpshowProjectsappjs
16
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Pattern
Controller in Typescript Classes
Packages the controller logic and makes it much easier to read and test
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjswhen(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
ltform name=loginForm class=navbar-form navbar-left form-signingt13 ltinput ng-model=loginuserName class=form-control placeholder=User Name required autofocusgt13 ltinput ng-model=loginpassword type=password class=form-control placeholder=Password requiredgt13 ltbutton ng-click=logindoLogin() class=btn btn-primary type=submitgtSign inltbuttongt13ltformgt
loginhtml
TypeScript Simple OO Code
AngularJS Creates an object in appjs
appjs
Optional Pattern
Named Controller Objects
Maintains modularity and avoids having to put data into scope objects which
hold so much other stuff making it easier to debug
when(login 13 controller LoginController as login13 templateUrl viewsloginhtml13 )13
17
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
class LoginController 13 $location ngILocationService13 password string13 userName string13 constructor($locationngILocationService) 13 this$location = $location13 thisuserName = 13 thispassword = 13 13 doLogin() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode(thisuserName thispassword)13 then((response) =gt thisonLoginSuccess(response))13 13 onLoginSuccess(response)13 if (responsestatus) 13 this$locationpath(showProjects)13 else 13 this$locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
function LoginController($scope $location) 13 $scopeuserName = 13 $scopepassword = 13 $scopedoLogin = function() 13 Call your login code with a call back to loginSuccessFn13 callSomeAuthCode($scopeuserName $scopepassword)13 then($scopeonLoginSuccess(response))13 13 $scopeonLoginSuccess = function(response)13 if (responsestatus) 13 $locationpath(showProjects)13 else 13 $locationpath(login)13 consolelog(Login failed You cannot proceed)13 13 1313
Typescript provides more readable structure
More funky
All initialization is in constructor Code completion No $scope
Initialization is not clearly demarcated declarations interspersed with execution
No code completion
1818
Controller in Typescript Classes
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
19
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
19
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
Single-Page ApplicationRich interactions within a single page loaded only once
Nav
igat
ion
Workspace
Actio
ns
Menu
20smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
21smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
21smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
If we have only one controller and one view how do we prevent our code from getting
bloated
22
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
Pattern Decompose view with directives
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
Directives to the rescue
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv class=rowgt13 ltdiv top-menu-view hellipgtltdivgt13 ltdivgt13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt13 13 hellip 13ltbodygt
23
templatehtmldirectivejs
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out about a selection in the Menu directive
24smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
But wait how do we pass data between directives
Nav
igat
ion
Workspace
Actio
ns
Menu
eg How does the Navigation directive find out which tree has been selected in the Menu directive
eg list of trees
25smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
26
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
angularmodule(myApp)13 controller(myController 13 function ($scope $route $routeParams $location) 13 $scopeaction = login13 $scope$on($routeChangeSuccess 13 function( $currentRoute $previousRoute ) 13 $scopeaction = $routecurrentaction13 )13 $scopelogin = function() 13 do login and on success13 $locationpath(home)13 13 $scopeonSelectTree = function(treeID) 13 go fetch the tree using the treeID hellip 1313 myTree holds the tree13 $scope$broadcast(treeLoaded 13 myTree myTree13 )13 13 )13
myController
navigation directive
angularmodule(myApp)13 directive(navigation function() 13 return 13 restrict A13 scope 13 myTree =13 13 13 templateUrl 13 link function(scope) 13 scope$on(treeLoaded function() 13 makeTreeWith(scopemyTree) 13 13 13 13 )13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
But wait how does scopeonSelectTree work correctly when called in the menu
directive
26
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
indexhtml
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
27
ltdiv top-menu-view hellipgtltdivgt13 13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
ltdiv top-menu-view menu-data=menuData on-select-tree=onSelectTree(treeID)gtltdivgt13
menu directive
angularmodule(myApp)13 directive(topMenuView function() 13 return 13 restrict A13 scope 13 menuData =13 onSelectTree amp13 13 13 templateUrl 13 link function(scope) 13 scopechooseTree = function(tree)13 scopeonSelectTree(treeID treeid)13 13 13 )13
28
Pattern Pass Controller Functions as Directive
Attributes
indexhtml
ltbody ng-app=myApp ng-controller=myControllergt13 ltdiv id=homescopegt13 ltdiv class=rowgt
13 13 ltdivgt1313 13 ltdiv class=rowgt13 ltdiv id=leftPanelgt13 ltdiv nav-widget hellipgtltdivgt13 ltdivgt13 ltdiv id=middlePanelgt13 ltdiv workspace-contents hellipgtltdivgt13 ltdivgt13 ltdiv id=rightPanel gt13 ltdiv action-menu hellipgtltdivgt13 ltdivgt13 ltdivgt13 ltdivgt1313 hellip13ltbodygt13
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
Legacy ApplicationNon-JS MVC model and cannot make direct web calls from JS
to your application
Generate HTML stubs that invoke ldquowidgetsrdquo using directives
29smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
30
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
30
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
31
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
ltdiv id=mywidgetOuterDivgt ltdiv id=mywidget class= ng-controller=MyWidgetCtrlgt ltdiv mywidget-directive input-data=inputData setup-data=setupData()gt ltdivgt ltdivgtltdivgt
angularbootstrap($(mywidgetOuterDiv) [myApp])var scope = $(mywidget)scope()scopesetupData(APPmyWidgetConfig)
In your legacy web application render this html
In your JS code bootstrap your widget
widget directive
widget controller
widget container
and this JSjsCode = APPmyWidgetConfig = inputData hellip
Pattern Dynamically invoke angular application
31
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejs
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
angularmodule(myApp) controller(MyWidgetCtrl function($scope) $scopesetupData = function(myWidgetConfigMyWidgetConfig) if ($scopeinputData ampamp myWidgetConfig) addTablesConfig = windowstandalonemyWidgetConfig else if ($scopeinputData ampamp myWidgetConfig) return $scopeinputData = myWidgetConfiginputData ) directive(mywidgetDirective function() var templateUrl = pathtotemplatehtml if (windowproduction) templateUrl = localpathtotemplatehtml return restrict A templateUrl templateUrl scope inputData = setupData amp link function (scope elem attrs ctrl) )
Data made available to directive scope
standalonejsPattern
Standalone Widget Mode
32
Allows for standalone widget testing
windowstandalone = myWidgetConfig inputData hellip
standalone indexhtml
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
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
33smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
Old ideas like modularity once-and-only-once etc still apply
They just look different
34smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
Get expert help
35
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
Join us tomorrow for a Test-Driven Development session
1045 AM
Check us out at httprangalcom and httpsmartorgcom
36smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev
Open House
Pattern Summary
Controller in Typescript classes (17)
Named Controller objects (17)
Decompose View with Directives (22)
Pass Controller Functions as Directive
Attributes (28)
Dynamically Invoke Angular Application (31)
Standalone Widget Mode (32)
37
Questions for reflection
Whatrsquos your AngularJS adoption experience
What have you learned
Write to usSomik Raha srahasmartorgcom
Kai Wu kwusmartorgcom
smartorgdev