Upgrade to Pro — share decks privately, control downloads, hide ads and more …

AngularJS @ DevWeek 2014

AngularJS @ DevWeek 2014

Video: http://vimeo.com/user22258446/review/91421794/91f15e0ea0

Source code:
https://github.com/pchen/DevWeek2014-Angular

You've probably heard of Backbone.js as a JavaScript MVC (Model-View-Controller) framework for building web apps, but it's worth exploring other options when you want to get more out of your framework. AngularJS is highly opinionated, which makes it easier for beginners to grasp core MVC concepts, while veteran web developers will enjoy its integration with automated testing suites. And for anyone who wants to write less boilerplate code? You will love Angular JS's two-way data binding abilities. Attend this session and Angular JS just might turn into your favourite MVC framework.

http://devweek.com/talks/19?type=Talk

Pearl Chen

April 01, 2014
Tweet

More Decks by Pearl Chen

Other Decks in Technology

Transcript

  1. A n g u l a rJ S a i

    n’ t j u s t a n o t h e r M VC f r a m e w o r k @ P e a r lC h e n Slides: go.klab.ca/devweek-angular
  2. My n a m e i s Pe a r

    l C h e n . H E L LO ! T h a n k s , D e v We e k !
  3. Te c h n o l o g i s

    t + E d u c a t o r I ’ M A … Karma Laboratory
  4. A n g u l a rJ S I ❤

    Adobe Flash with ActionScript 2 & AS3 Adobe Flex with ActionScript 3 HTML, CSS, & JS with AngularJS
  5. W h a t i s A n g u

    l a rJ S ? I N T R O
  6. W h a t i s A n g u

    l a rJ S ? I N T R O angularjs.org
  7. W h a t i s A n g u

    l a rJ S ? I N T R O
  8. Given this JavaScript string: name  =  'DevWeek  2014'; The old

    school way to dynamically update DOM text: <div  id="conference"></div>   document.getElementById('conference') Things got easier with the jQuery $(selector): <div  id="conference"></div>   $('#conference') Now, with Angular! <div>{{name}}</div> .textContent  =  name; .text(  name  );
  9. AngularJS is a JavaScript MVC framework
 but… “there is nothing

    to inherit, nothing to call, and 
 no complex life cycle for your controllers to follow. […] It really is just a better browser.” - Misko Hevery, creator of AngularJS
 Appliness (Feb #11)
  10. B e g i n n e r / i

    n t e r m e d i a t e ? W H Y A N G U L A R ? • Declarative ➞ Readable • Spaghetti code • Does a lot of heavy lifting for you • Opinionated == good
  11. Mo r e a d v a n c e

    d ? W H Y A N G U L A R ? • Create complex web apps with less code. • Write code with unit testing in mind.
  12. Mo d e l -Vi e w - C o

    n t ro l l e r M V C R E F R E S H E R
  13. Model
 your application data Controller
 mediator between the view &

    model View
 a representation
 of the model data M V C R E F R E S H E R x user input database save REST result update DOM
  14. Mo d e l -Vi e w -W h a

    t e v e r M V C R E F R E S H E R L I N K
  15. Re c o m m e n d e d

    Re a d i n g M V C ( O R J AVA S C R I P T ) R E F R E S H E R
  16. Pa r t 1 : O v e r v

    i e w A G E N D A Module building blocks: • directives (built in) • controllers + $scope • modules + dependency injection The basics: • getting started • 2-way data binding • template expressions
  17. Pa r t 2 : To o l s A

    G E N D A • Batarang for Chrome DevTools • Yeoman for scaffolding • Testing tools • Text editor plugins
  18. Pa r t 3 : G o i n g

    d e e p e r A G E N D A • Custom directives • $watch and $apply
  19. G e t t i n g s t a

    r t e d PA R T 1 : A N G U L A R O V E R V I E W
  20. A s i m p l e A n g

    u l a r t e m p l a t e D E M O <html>      <body  ng-­‐app>          <div>              <label>What’s  your  name?</label>              <input  type="text"  ng-­‐model="yourName">              <h1>Hello  {{yourName}}!</h1>          </div>          <script  src="angular.js"></script>      </body>   </html>
  21. <html>      <body  ng-­‐app>          <div>

                 <label>What’s  your  name?</label>              <input  type="text"  ng-­‐model="yourName">              <h1>Hello  {{yourName}}!</h1>          </div>          <script  src="angular.js"></script>      </body>   </html> I n c l u d e t h e a n g u l a r . j s s c r i p t <script  src="angular.min.js"></script> Ready for production? LO A D LO C A L LY O R F R O M A C D N
  22. <html>      <body  ng-­‐app>          <div>

                 <label>What’s  your  name?</label>              <input  type="text"  ng-­‐model="yourName">              <h1>Hello  {{yourName}}!</h1>          </div>          <script  src="angular.js"></script>      </body>   </html> B o o t s t r a p y o u r a p p <html  ng-­‐app></html> <div  ng-­‐app></div> Need to manipulate stuff in <head>? Only making a small widget? U S E T H E n g A p p D I R E C T I V E O N T H E PA R E N T N O D E
  23. <html>      <body  ng-­‐app>          <div>

                 <label>What’s  your  name?</label>              <input  type="text"  ng-­‐model="yourName">              <h1>Hello  {{yourName}}!</h1>          </div>          <script  src="angular.js"></script>      </body>   </html> M a ke i t A n g u l a r A D D OT H E R D I R E C T I V E S L I K E n g M o d e l A D D S O M E T E M P L AT E E X P R E S S I O N S
  24. Te m p l a t e e x p

    r e s s i o n s PA R T 1 : A N G U L A R O V E R V I E W
  25. O u t p u t t i n g

    v a l u e s T E M P L AT E E X P R E S S I O N S • Expressions are JavaScript-like code snippets. • Double curly brace notation
 e.g. {{simpleVariable}}  or {{object.simpleVariable}} • Evaluate and bind to primitives
 Strings, numbers, and booleans • undefined and null values will show up blank. D E M O
  26. F l o w c o n t ro l

    T E M P L AT E E X P R E S S I O N S • There is none! • No looping or conditionals within {{  }}. • Handle business logic with methods in a controller or via a directive.
  27. v s D i r e c t i v

    e e x p r e s s i o n s T E M P L AT E E X P R E S S I O N S • You might come across something like this:
 <a  ng-­‐href="img/{{username}}.jpg">Hello  {{username}}!</a> • But what about this?
 <div  ng-­‐class="{'highlight':isHighlighted}"></div> • Object literal notation
 e.g. {'stringToOutput':booleanCondition} • Not exactly the same as {{ }}. 
 Evaluated in the directive. Think: function parameter. D E M O
  28. D a t a b i n d i n

    g PA R T 1 : A N G U L A R O V E R V I E W
  29. 1 - w ay b i n d i n

    g D ATA B I N D I N G <input  type="text"  value="{{yourName}}">   <h1>{{yourName}}</h1> yourName   hardcoded  to  'Pearl' <h1>{{yourName}}</h2> value="{{yourName}}" Pearl Pearl 1 -WAY M E R G E
  30. <input  type="text"                

                           >   <h1>{{yourName}}</h1> 2 - w ay b i n d i n g D ATA B I N D I N G yourName   hardcoded  to  'Pearl' <h1>{{yourName}}</h2> value="{{yourName}}" model becomes
 single source of truth L I N K E D L I N K E D ng-­‐model="yourName" value="{{yourName}} D E M O A U T O U P D AT E S Pearl Pearl
  31. H T M L C o m p i l

    e r D ATA B I N D I N G • The Angular compiler consumes the DOM, 
 not string templates. • Currently uses "dirty checking". • Object.observe in future versions of Angular.
  32. Pa r t 1 : O v e r v

    i e w A G E N D A Module building blocks: • directives (built in) • controllers + $scope • modules + dependency injection The basics: getting started 2-way data binding template expressions
  33. D i r e c t i v e s

    
 ( b u i l t i n a n d o t h e r l i b r a r i e s ) PA R T 1 : A N G U L A R O V E R V I E W
  34. Angular directives teach DOM elements new tricks! • Use directives

    to enhance existing elements
 <div  ng-­‐class="{'highlight':isSelected}"></div> • Create directives to encapsulate DOM functionality
 <date-­‐picker></date-­‐picker> W h a t i s a d i r e c t i v e ? D I R E C T I V E S
  35. Us i n g d i r e c t

    i v e s D I R E C T I V E S Syntax-wise, it can be a: • tag attribute
 <div  ng-­‐show="isTrue"></div>
 <div  ng-­‐non-­‐bindable></div>   • existing or custom HTML tag
 <form></form>
 <date-­‐picker></date-­‐picker> • css class
 <li  class="ng-­‐class-­‐even"></li>
 <li  class="ng-­‐class-­‐odd"></li>
  36. B u i l t - i n d i

    r e c t i v e s D I R E C T I V E S Control • ng-repeat • ng-if / ng-switch Events • ng-click / ng-submit • ng-focus / ng-blur • ng-cut / ng-copy / ng-paste These are only some of them! Go to docs.angularjs.org/api/ng/directive for the full list. CSS • ng-class / ng-style • ng-show / ng-hide • ng-class-even / ng-class-odd Forms • form / input / select / textarea • ng-model • ng-selected / ng-checked • ng-required / ng-disabled
  37. n g - w h a t ? D I

    R E C T I V E N A M E S PA C I N G <html> Angular Angular
  38. n g W h a t ? ? D I

    R E C T I V E N A M E S PA C I N G ng-click ??? ngClick N O R M A L I Z AT I O N
  39. Mo d u l e n a m e n

    o r m a l i z a t i o n D I R E C T I V E S Directive names automatically get converted. • camelCase used in JavaScript 
 angular.module('myApp',  [])
    .directive('myDirective',  function()  {
        //  return  
    });   • dashes used in HTML
 <my-­‐directive>, <div  my-­‐directive> , <div  class="my-­‐directive">
  40. H T M L 5 c o m p l

    i a n c y D I R E C T I V E S Need to run your markup through a validator? • Add the data-­‐ prefix: data-­‐ng-­‐directive   • x-­‐ng-­‐directive  for experimental vendor-specific feature Colons and underscores work too… but they are considered legacy: • ng:directive, data-­‐ng:directive, or x:ng_directive
  41. E x a m p l e : D 3

    D I R E C T I V E S From odiseo.net/angularjs/proper-use-of-d3-js-with-angular-directives: <div  ng-­‐app="myApp"  ng-­‐controller="Ctrl">      <bars-­‐chart  chart-­‐data="myData"></bars-­‐chart>   </div>
  42. E x a m p l e : C h

    a r t J S D I R E C T I V E S From blog.safaribooksonline.com/2013/11/07/creating-an-angularjs-component/: <chart-­‐js  id="chart1"            width="chart.width"            height="chart.height"            title="{{chart.title}}"            type="{{chart.type}}"          data="{{chart.data}}"          ng-­‐model="chart">   </chart-­‐js>
  43. E x a m p l e : Ic o

    n i c Fr a m e w o r k D I R E C T I V E S ionicframework.com
 >> /docs/angularjs/controllers/side-menu/ <ion-­‐side-­‐menu  side="left">      <ion-­‐content  scroll="false">          <ion-­‐list>              <ion-­‐item                      ng-­‐repeat="project  in  projects">                  {{project.title}}              </ion-­‐item>          </ion-­‐list>      </ion-­‐content>   </ion-­‐side-­‐menu>
  44. C o n t ro l l e r s

    a n d $ s c o p e PA R T 1 : A N G U L A R O V E R V I E W
  45. G e t t i n g o r g

    a n i z e d C O N T R O L L E R S • Views are for HTML output. • Directives are for DOM manipulation. • Controllers are for your business logic.
  46. B u i l d a b u g t

    r a c ke r a p p C O N T R O L L E R S Let's build a "bug tracker app". Features of this app: 1. 2. 3.
  47. 1 . T h e v i e w <body

     ng-­‐app>      <p>          {{counter}}  days  since  a  bug  was  found      </p>      <div>          <button>              No  bugs  found  today!  :)          </button>          <button>              A  bug  was  found  :(          </button>      </div>      <script  src="angular.js"></script>   </body> D E M O
  48. <body  ng-­‐app>      <p>          {{counter}}

     days  since  a  bug  was  found      </p>      <div  ng-­‐init="counter=0">          <button  ng-­‐click="counter=counter+1">              No  bugs  found  today!  :)          </button>          <button  ng-­‐click="counter=0">              A  bug  was  found  :(          </button>      </div>      <script  src="angular.js"></script>   </body> 2 . A d d i n g l o g i c t o t h e v i e w D E M O
  49. <body  ng-­‐app>      <p  ng-­‐style="style"        

       ng-­‐init="style={'background-­‐color':'rgba(223,240,216,0)'}">          {{counter}}  days  since  a  bug  was  found      </p>      <div  ng-­‐init="counter=0">          <button  ng-­‐click="counter=counter+1;            style={'background-­‐color':'rgba(223,240,216,'+counter/20+')'}">              No  bugs  found  today!  :)          </button>          <button  ng-­‐click="counter=0;            style={'background-­‐color':'rgba(223,240,216,0)'}">              A  bug  was  found  :(          </button>      </div>      <script  src="angular.js"></script>   </body> 3 . A d d i n g m o r e l o g i c t o t h e v i e w D E M O
  50. <body  ng-­‐app>      <p  ng-­‐style="style"        

       ng-­‐init="style={'background-­‐color':'rgba(223,240,216,0)'}">          {{counter}}  days  since  a  bug  was  found      </p>      <div  ng-­‐init="counter=0">          <button  ng-­‐click="counter=counter+1;            style={'background-­‐color':'rgba(223,240,216,'+counter/20+')'}">              No  bugs  found  today!  :)          </button>          <button  ng-­‐click="counter=0;            style={'background-­‐color':'rgba(223,240,216,0)'}">              A  bug  was  found  :(          </button>      </div>      <script  src="angular.js"></script>   </body> 4 . A d d i n g e v e n m o r e l o g i c … S TO P
  51. <body  ng-­‐app>      <div  ng-­‐controller="MagicCtrl">        <input

     type="number"  ng-­‐model="{{counter}}">        <p>{{counter}}</p>      </div>      <script>          function  MagicCtrl($scope)  {              $scope.counter  =  0;          }      </script>      <script  src="angular.js"></script>   </body> C r e a t i n g a n A n g u l a r c o n t ro l l e r C O N T R O L L E R S U S E T H E n g C o n t r o l l e r D I R E C T I V E S A M E N A M E
  52. <body  ng-­‐app>      <div  ng-­‐controller="MagicCtrl">        <input

     type="number"  ng-­‐model="{{counter}}">        <p>{{counter}}</p>      </div>      <script>          function  MagicCtrl($scope)  {              $scope.counter  =  0;          }      </script>      <script  src="angular.js"></script>   </body> D e p e n d e n c y i n j e c t i o n o f $ s c o p e C O N T R O L L E R S D O N ' T N E E D $ s c o p e H E R E G E T / S E T V I A $ s c o p e .
  53. <body  ng-­‐app>      <p  ng-­‐style="style"        

       ng-­‐init="style={'background-­‐color':'rgba(223,240,216,0)'}">          {{counter}}  days  since  a  bug  was  found      </p>      <div  ng-­‐init="counter=0">          <button  ng-­‐click="counter=counter+1;            style={'background-­‐color':'rgba(223,240,216,'+counter/20+')'}">              No  bugs  found  today!  :)          </button>          <button  ng-­‐click="counter=0;            style={'background-­‐color':'rgba(223,240,216,0)'}">              A  bug  was  found  :(          </button>      </div>      <script  src="angular.js"></script>   </body> 4 . P u t l o g i c i n t o a c o n t ro l l e r
  54. <div  ng-­‐controller="CounterCtrl">      <p  ng-­‐style="style">        

     {{counter}}  days  since  a  bug  was  found      </p>      <div>          <button  ng-­‐click="incrementCounter()">              No  bugs  found  today!  :)          </button>          <button  ng-­‐click="resetCounter()">              A  bug  was  found  :(          </button>      </div>   </div>   <script  src="angular.js"></script>   <script>      function  CounterCtrl($scope)  {  …  }   </script> 4 . P u t l o g i c i n t o a c o n t ro l l e r D E M O
  55. <div  ng-­‐controller="CounterCtrl">      <p  ng-­‐style="style">        

     {{counter}}  days  since  a  bug  was  found      </p>      <div>          <button  ng-­‐click="incrementCounter()">              No  bugs  found  today!  :)          </button>          <button  ng-­‐click="resetCounter()">              A  bug  was  found  :(          </button>      </div>   </div>   <script  src="angular.js"></script>   <script  src="counter-­‐ctrl.js"></script> 5 . E x t e r n a l i z e c o n t ro l l e r D E M O
  56. Wi t h o u t $ s c o

    p e ( n e w e r s y n t a x ) C O N T R O L L E R S N E E D A L I A S H E R E N O $ s c o p e S O U S E t h i s . N E W A L I A S <body  ng-­‐app>      <div  ng-­‐controller="MagicCtrl  as  ctrl">        <input  type="number"  ng-­‐model="{{ctrl.counter}}">        <h1>{{ctrl.counter}}!</h1>      </div>      <script>          function  MagicCtrl()  {              this.counter  =  0;          }      </script>      <script  src="angular.js"></script>   </body> D E M O
  57. A r r ay s w i t h n

    gRe p e a t C O N T R O L L E R S • In your controller:
 $scope.todos  =  ["Learn  Angular",  
                                "Make  awesome  apps",  
                                "Rule  the  world"];   • In your template:
 <ul  ng-­‐repeat="todo  in  todos">
    <li>{{todo}}</li>
 </ul> D O C S
  58. Fo r m s o b j e c t

    s C O N T R O L L E R S • In your controller:
 $scope.user  =  {  name:  'Pearl',  
                                email:  '[email protected]',
                                subscribe:  true  };   • In your template:
 <input  type="text"  ng-­‐model="user.name">
 <input  type="email"  ng-­‐model="user.email">
 <input  type="checkbox"  ng-­‐model="user.subscribe"> D O C S
  59. Mo d u l e s a n d d

    e p e n d e n c y i n j e c t i o n PA R T 1 : A N G U L A R O V E R V I E W
  60. Mo d u l a r c o m p

    o n e n t s M O D U L E S A N D D E P E N D E N C Y I N J E C T I O N Angular modules are just object containers. • Top-level module is like an application namespace • Stores your controllers, directives, etc • Declare what is required as a dependency • Angular takes care of bootstrapping module 
 vs developer having to declare & initialize it manually. D O C S
  61. Mo d u l e s y n t a

    x M O D U L E S A N D D E P E N D E N C Y I N J E C T I O N • Create top-level application module: • <body  ng-­‐app="demoApp">…</body>   • angular.module('demoApp',  []); • Add another module like a controller:   • angular.module('demoApp')
    .controller('MagicCtrl',  function  ($scope)  {
        //  $scope.stuff  =  'goes  here';
    });   • <script  src="magic.js"></script> D O C S
  62. Mo d u l e s y n t a

    x M O D U L E S A N D D E P E N D E N C Y I N J E C T I O N Note the subtle difference: • Create:
 angular.module('demoApp',  []);   • Retrieve:
 var  myModule  =  angular.module('demoApp');
  63. D e p e n d e n c y

    i n j e c t i o n M O D U L E S A N D D E P E N D E N C Y I N J E C T I O N • Declare an application with no dependencies:
 angular.module('demoApp',  []);   • Declare a dependency on the URL routing module:
 angular.module('demoApp',  ['ngRoute']);   • Declare even more dependencies:
 angular.module('demoApp',  ['ngRoute','ngResource',   'ngCookies']);
  64. D e p e n d e n c y

    i n j e c t i o n M O D U L E S A N D D E P E N D E N C Y I N J E C T I O N • Each dependency should be a separate .js file:   • angular.module('demoApp',  
 ['ngRoute','ngResource',  'ngCookies']);   • <script  src="angular-­‐route.js"></script>  
 <script  src="angular-­‐resource.js"></script>
 <script  src="angular-­‐cookies.js"></script>   • Use a concat script (via Grunt or Gulp) to compile them all into 1 file when ready to deploy.
  65. Pa r t 1 : O v e r v

    i e w A G E N D A Module building blocks: directives (built in) controllers + $scope modules + dependency injection The basics: getting started 2-way data binding template expressions questions? Let's recap, then…
  66. Re c a p : a l l t o

    g e t h e r n o w PA R T 1 : A N G U L A R O V E R V I E W
  67. Re w r i t i n g a s

    i m p l e " a p p" R E C A P : A L L TO G E T H E R N O W Going from jQuery to AngularJS D E M O
  68. C o m p a r i n g t

    h e c o d e R E C A P : A L L TO G E T H E R N O W C O M PA R E
  69. B e n e f i t s R E

    C A P : A L L TO G E T H E R N O W Model-driven data binding means: • descriptive state variables —> code is better at
 "self documenting" • less code needed for DOM manipulation • business logic decoupled from the view • behavioural intentions are more clear in the HTML
  70. Pa r t 1 : O v e r v

    i e w A G E N D A Module building blocks: directives (built in) controllers + $scope modules + dependency injection The basics: getting started 2-way data binding template expressions Questions?
  71. Pa r t 2 : To o l s A

    G E N D A • Batarang for Chrome DevTools • Yeoman for scaffolding • Testing tools • Text editor plugins
  72. B a t a r a n g PA R

    T 2 : O T H E R T O O L S
  73. I n s t a l l f ro m

    C h ro m e S t o r e B ATA R A N G chrome.google.com/webstore > "Batarang"
  74. Ye o m a n fo r A n g

    u l a r PA R T 2 : O T H E R T O O L S
  75. S c a f fo l d y o u

    r a p p Y E O M A N F O R A N G U L A R Tutorial: yeoman.io/codelab.html
  76. To g e t s t a r t e

    d Y E O M A N F O R A N G U L A R $  [sudo]  npm  install  -­‐-­‐global  yo   $  yo   $  [sudo]  npm  install  -­‐g  generator-­‐angular   $  yo  angular  [app-­‐name]   $  bower  install  -­‐-­‐save  angular-­‐cookies   $  grunt  serve
  77. W h i l e y o u ' r

    e c o d i n g … Y E O M A N F O R A N G U L A R $  yo  angular:controller  [controllerName]   $  yo  angular:view  [viewName]   $  yo  angular:route  [routeName]   $  yo  angular:directive  [directiveName]   $  grunt  test All of the commands: github.com/yeoman/generator-angular
  78. Re a d y t o r e l e

    a s e ? Y E O M A N F O R A N G U L A R $  grunt  build
  79. Te s t i n g PA R T 2

    : O T H E R T O O L S
  80. K a r m a T E S T I

    N G karma-runner.github.io
  81. Ja s m i n e T E S T

    I N G jasmine.github.io
  82. Us e d t o g e t h e

    r T E S T I N G • Karma test runner is for running your JS tests. • Jasmine is the syntax for describing your tests. • it('should  attach  awesomeThings  to  scope',  function  ()  {
        expect(scope.awesomeThings.length).toBe(3);
    });   • Tests automatically get generated with Yeoman generator-angular — so no excuses!
  83. P ro t r a c t o r T

    E S T I N G github.com/angular/protractor
  84. P ro t r a c t o r T

    E S T I N G • Use for end-to-end (e2e) functional testing • Wrapper for Selenium WebDriver • Uses Jasmine and "page objects" for its specs. • Fairly new so not part of Yeoman generator-angular — yet?
  85. Te x t e d i t o r p

    l u g i n s PA R T 2 : O T H E R T O O L S
  86. Fo r S u b l i m e Te

    x t T E X T E D I TO R P LU G I N S github.com/angular-ui/AngularJS-sublime-package
  87. Fo r o t h e r s T E

    X T E D I TO R P LU G I N S docs.angularjs.org/guide#tools
  88. Pa r t 2 : To o l s A

    G E N D A Batarang for Chrome DevTools Yeoman for scaffolding Testing tools Text editor plugins Questions?
  89. Pa r t 3 : G o i n g

    d e e p e r A G E N D A • Custom directives • $watch and $apply
  90. PA R T 3 : G O I N G

    D E E P E R C u s t o m d i r e c t i v e s 
 ( a k a " b u i l d y o u r o w n" )
  91. D i r e c t i v e s

    r e f r e s h e r C U S T O M D I R E C T I V E S Syntax-wise, it can be a: • tag attribute
 <div  ng-­‐show="isTrue"></div>
 <div  ng-­‐non-­‐bindable></div>   • existing or custom HTML element
 <form></form>
 <date-­‐picker></date-­‐picker> • css class
 <li  class="ng-­‐class-­‐even"></li>
 <li  class="ng-­‐class-­‐odd"></li>
  92. D e f i n i n g c u

    s t o m d i r e c t i v e s C U S T O M D I R E C T I V E S • angular.module('demoApp')
    .directive('myTooltip',  function  ()  {
        return  directiveObject;
 });
  93. D i r e c t i v e d

    e f i n i t i o n o b j e c t C U S T O M D I R E C T I V E S
  94. D i r e c t i v e d

    e f i n i t i o n o b j e c t C U S T O M D I R E C T I V E S table from "AngularJS"
  95. To p 4 p ro p e r t i

    e s C U S T O M D I R E C T I V E S • restrict: 'E', 'A', 'C', or 'M' (or a combo 'AC') • template: '<div>Stuff</div>'
 or templateUrl: 'myTemplate.html'   • link: function  postLink(scope,  elem,  attrs)  {
              //  do  scope.stuff  here
          } • scope: false (default), true, or {attribute:'@=&'}
  96. Re s t r i c t C U S

    T O M D I R E C T I V E S • tag attribute
 'A'   • existing or custom HTML element
 'E' • css class
 'C'   • HTML comment
 'M'
  97. S c o p e C U S T O

    M D I R E C T I V E S • bind to object property in parent scope
 '='   • pass as string
 '@' • bind to function in parent scope
 '&'
  98. S a m p l e p ro j e

    c t C U S T O M D I R E C T I V E S designresearchtechniques.com
  99. S a m p l e c o d e

    C U S T O M D I R E C T I V E S github.com/pchen/telus-mobility-web-stats
  100. PA R T 3 : G O I N G

    D E E P E R $ w a t c h a n d $ a p p l y
  101. $ w a t c h $ WATC H A

    N D $ A P P LY Listen for changes in your properties: scope.$watch('watchExpression',  function(){
    //  do  stuff  now  that  watchProperty  has  changed
 }); D O C S
  102. $ w a t c h $ WATC H A

    N D $ A P P LY Example, state changes in one file:
 scope.filterByTop10  =  function(event){
    event.preventDefault();
    scope.showInPhase  =  '';  //clear  out  phase  filters
    scope.showTop10  =  true;
 }; Listening for the change:
 scope.$watch('showTop10',  function(){
    if  (  scope.appendix.length  >  0  )  {
        scope.filteredAppendix  =  $filter('masterTechniqueFilter')
                                            (scope.appendix,  scope.showInPhase,  scope.showTop10);
    }
 });
  103. $ a p p l y $ WATC H A

    N D $ A P P LY Use $apply to execute an expression in angular from outside of the angular framework. scope.$apply('expression');   e.g. browser DOM events, setTimeout, XHR or third party libraries D O C S
  104. $ a p p l y $ WATC H A

    N D $ A P P LY Example DOM event: element.on('mouseover',  'li',  function(event){
    var  technique  =  angular.element(  event.target  ).scope().technique;
    scope.$apply(function(){
        scope.selectedTechnique  =  technique;
    });
 });
  105. Pa r t 3 : G o i n g

    d e e p e r A G E N D A Custom directives $watch and $apply Questions?
  106. TWITTER @PearlChen GOOGLE+ klab.ca/+ P E A R L C

    H E N T h a n k y o u ! 
 ( D e m o s : g i t h u b . c o m / p c h e n / D e v We e k 2 0 1 4 -A n g u l a r ) F I N