Angular from Scratch


Published on

A two-hour introduction to AngularJS, delivered at the Angular Meetup DC, on 11/13/13. Demo files available at

Published in: Technology, Business

Angular from Scratch

  1. 1. FROM SCRATCH! @ Angular Meetup DC, 11/13/13 by: Christian Lilley Friday, November 15, 13 @XMLilley
  2. 2. GOALS & ASSUMPTIONS • We’re all familiar with basic Javascript & HTML & MVC terminology, but maybe not Angular’s take on it. • Yeoman is awesome. But the Yeoman way and the basic (naïve) way aren’t really compatible in a 2-hr session. We’ll leave Yeoman for another day. •I wish there was more time for audience hands-on tonight, but Angular’s a big topic. So, all the demo code is available for take-home experimentation. • Save questions for breaks & the end, pls. I’ll stick around. Friday, November 15, 13
  3. 3. ANGULAR BUZZWORDS Full Application Framework, not a Library • MV* • Convenient Abstractions • Total Modularity, Reusability • Pub-Sub Communications Between Modules • Dependency Injection • Routing, Deep-Linking, History • Filters, Expression Interpolation • Friday, November 15, 13 Data-Binding • HTML Templating • Testing Baked-In (Karma) • Integrated Promises ($Q) • Localization • Form Validation • “Big UI” • MIT License •
  4. 4. ANGULAR IS ALL ABOUT... • MV*: A data model, templates for viewing/interacting with it, and logic in controllers, services, directives, etc. • Declarative Behavior: Protect Extend HTML. HTML is right for templates, not JS. Intentions are visible in templates. • Data-Binding: User or Program can modify the model, and views update automagically to reflect those changes. • Model-Driven Behavior: DOM / View updates based on model, not brittle imperative logic. Truth in DOM Model. • Modular Architecture, Separated Concerns: DOM changes in Directives, model changes in Controllers, abstracted app-wide support functions & data in Services Friday, November 15, 13
  5. 5. Let’s get started! Friday, November 15, 13
  6. 6. Friday, November 15, 13
  7. 7. Bootstrapping Your App The ng-app directive tells Angular what part of your main template it needs to watch. It ‘wakes up’ Angular. You can (should) define a specific Angular module to serve as the core app logic: ng-app=‘myModule’ You can also bootstrap manually, if you need to. Friday, November 15, 13
  8. 8. Data-Binding Angular’s declarative 2-way databinding is part of its special sauce. Changing data automagically Changing data automagically in the model updates the view. in the view updates the model. model -> view -> model -> view LET ANGULAR DO THIS FOR YOU! It’s part of Angular’s emphasis on model-driven UI. Friday, November 15, 13
  9. 9. DOM Then shows final outcome in the DOM Angular watches for changes here Don’t do imperative DOM Changes! Consequent model changes by Angular MODEL Model Changes can start anywhere Friday, November 15, 13 Updates the model accordingly Truth lives Here! Not in DOM!
  10. 10. Tells Angular: “Watch this space” Tells Angular: “Bind this input.” Tells Angular: “Insert Data here.” Friday, November 15, 13
  11. 11. But what about those curly-brackets? ANGULAR EXPRESSIONS Friday, November 15, 13
  12. 12. With an Angular Expression, You Can: Do math, or comparison Concatenate text Reference a model property Invoke a function But not: Control Flow, like conditions or loops (app logic belongs in controllers) Friday, November 15, 13
  13. 13. One more thing you can do: Filter the output of the expression Filters are applied by ‘piping’ an expression into one: {{modelName.propertyName  |  filterName:arg}} Friday, November 15, 13
  14. 14. DEMO DEMO DEMO Friday, November 15, 13
  15. 15. So, How Can we Build a More Complicated App Than This? Organize code with MODULES Friday, November 15, 13
  16. 16. Modules are where we put our code: like filters, controllers, directives, services, and configuration information. They provide us with encapsulation and re-usability for macro-level groupings of code. Note that angular.module(‘moduleName’) is both a creator and a retriever. Friday, November 15, 13
  17. 17. And when we want to organize our data (view-models), too? Organize view data & functions with CONTROLLERS Friday, November 15, 13
  18. 18. Controllers Intro Controllers are function Instances, used for interacting w/ data in views: They’re created and destroyed along with elements/templates. multiple invocations = multiple instances If you want persistence, either place on an element that’s persistent, or place the data/methods in a service (more later). Hard to address a *specific* controller, so use events for communication (more later). Friday, November 15, 13
  19. 19. DEMO DEMO DEMO Friday, November 15, 13
  20. 20. Services Intro Services are ludicrously simple: Remember (from, like, 1 slide ago), how controllers are created and destroyed every time you need one? And there can be lots of instances of a single controller type? Services, by contrast, are unicorns, and last forever. (jargon: ‘lazy-loaded singletons’) Friday, November 15, 13
  21. 21. Templates/Views Intro In Angular, HTML is the template language! Use inline HTML, external files, or simple strings as templates. Then use expressions (and directives) to insert data from your model into the view. Re-use templates with different controllers, re-use controllers with different templates. Friday, November 15, 13
  22. 22. DEMO DEMO DEMO Friday, November 15, 13
  23. 23. Routing Intro Since we’re extending HTML in our templates, let’s extend the browser too. Routing lets you drive your interface views using the content of the location/URL bar. This lets our Angular Apps behave just like the server-side apps that users are used to, with forward/back and deep-linking to specific content. Friday, November 15, 13
  24. 24. DEMO DEMO DEMO Friday, November 15, 13
  25. 25. Directives Intro Controllers are just for data interactions. So DOM code has to go somewhere. Directives it is. Modular, re-usable, de-coupled DOM logic. Directives embody all of Angular’s major design principles. Way easier to use than the (old) Angular docs make it seem. We’ll have you writing your own in no time. Friday, November 15, 13
  26. 26. Directive Pop-Star: NG-REPEAT Everybody digs it: throw a series of data into your view super-easily. Like ‘collection-views’ in other libraries filter/sort the output if you like Friday, November 15, 13
  27. 27. DEMO DEMO DEMO Friday, November 15, 13
  28. 28. Coming up... the DEETS First... Questions? Friday, November 15, 13
  29. 29. CONTROLLERS In (a smidge more) Detail Friday, November 15, 13
  30. 30. About Controllers Best-practice: use controller only for dealing with data/model. Let directives handle updating the views based on the properties of the model. Two ways to define: using .controller() method on a module As an ordinary named function (This will wind up on global scope. No good reason to do this. Just recognize it if you see it.) Friday, November 15, 13
  31. 31. TEMPLATES/VIEWS In Detail Friday, November 15, 13
  32. 32. Templates Demo Note: when we provide the name of a template in the declaration of a directive like ng-include, we have to wrap it in a second pair of quotes. The first pair of quotes delimits an expression, which will be eval()’d by Angular. Since we supply a template path as a string, it needs the quotes. We could also reference a property on the model, without needing to do that. Friday, November 15, 13
  33. 33. Templates/Views We can include templates conditionally, using directives like ng-show/ng-hide, ng-if, ng-switch (We’ll also demonstrate how to use custom directives as another way to include a template.) But the most powerful way to conditionally show content, is to use the browser’s address bar. Which means we want... Friday, November 15, 13
  34. 34. Templates SNAFU Browsers don’t like to let you access external local files. This sets off ‘sameorigin’ errors. Simple solution: start a server. Painless Javascript/Node approach: >>  sudo  npm  install  -­‐g  http-­‐server >>  http-­‐server  (or:  `node  bin/http-­‐server`) But, no logging! ‘Ole-reliable Python option with logging: >>  python  -­‐m  SimpleHTTPServer  8000 Or, the faster ‘Twisted’ (comes w/ OSX): >>  twistd  -­‐no  web  -­‐-­‐path=. Friday, November 15, 13
  35. 35. Templates SNAFU Or, you can just use Yeoman/Grunt: >>  grunt  server (do this) Friday, November 15, 13
  36. 36. ROUTING In Detail Friday, November 15, 13
  37. 37. First: $location Angular’s $location service is bound to window.location (ie. to what’s in the browser’s ‘address bar’) Changes to the URL in the address bar are reflected in $location & changes to $location are reflected in address bar. ‘Back’ & ‘Forward’ are supported, as is deep-linking See: “Using $location” guide Friday, November 15, 13
  38. 38. $route The $route service (configured via $routeProvider) gives us the ability to react programmatically to changes in the $location (plus $routeParams). We specify a template that will be rendered inside an <ng-view> in response to a given route-change, along with its controller and some other details. Friday, November 15, 13
  39. 39. Routing Is A Config For Your App Module Fundamentally, routing works as a configuration detail on your base application module. (The one in ng-app.) There are two ways to configure your app: by supplying a config function at module creation, or by invoking the config function on your app after creation... Friday, November 15, 13
  40. 40. 2 Ways to Config App A config function is the (unpopular) third argument to a module’s creation: myModule = angular.module(name, [dependencies], function(injectables) { // Configuration details, like routing }); Or, after the fact w/ Module.config( ) myModule.config(function(injectables) { // Configuration details, like routing }); Friday, November 15, 13
  41. 41. Routing Syntax Routes are added via configuration methods called on $routeProvider in the app config function. There are only two basic methods involved: $routeProvider.when(path, route) $routeProvider.otherwise(params) Friday, November 15, 13
  42. 42. Route Config Object We can include an optional route config object for each path, with the following options: template: html template as string templateUrl: path to a partial controller: binds an instance of specified controller to the template instance redirectTo: a path string or a function that returns one resolve: a function or service reference that will execute (or promise that resolves) before $routeChangeSuccess Friday, November 15, 13
  43. 43. Routing Example myModule.config(function($routeProvider) { $routeProvider .when('/home', { templateUrl: 'home.html', controller: homeCtrl }) .when('/index', { redirectTo: '/home’ }) .when('/archive/doc/:docId', { templateUrl: 'archive_doc.html', controller: archCtrl }) .when('/contact', { templateUrl: 'poc.html', controller: pocCtrl, resolve: { // I will cause a 1 second delay delay: function($q, $timeout) { var delay = $q.defer(); $timeout(delay.resolve, 1000); return delay.promise; }}) .otherwise({ redirectTo: '/home' }); }); Friday, November 15, 13
  44. 44. .otherwise() The only property in the .otherwise() config object is redirectTo NOTE: the value of redirectTo should be a path, like ‘/home’, not a template location like ‘home.html’. The route for ‘/home’ will then take care of supplying the template. myModule.config(function($routeProvider) { $routeProvider .when('/home', { templateUrl: 'home.html', controller: homeCtrl }) .otherwise({ redirectTo: '/home' }); }); Friday, November 15, 13
  45. 45. Named Groups in Path The path can contain ‘named groups’ starting with a colon (/path/path/:name). All characters between colon and next slash are matched and stored in $routeParams. From $routeParams, you can access that data and use it in preparing the view, based on related data. Good technique for dynamically including data from a collection: users, products, chapters, etc. Friday, November 15, 13
  46. 46. Named Groups in Path example definition from Angular docs: $routeProvider.when('/Book/:bookId/ch/:chapterId', {templateUrl: 'chapter.html', controller: ChapterCntl }); Example URL: // The Route Params you’ll see for that: $routeParams = {"bookId":"Moby","chapterId":"1"} Friday, November 15, 13
  47. 47. $scope & Models In Detail Friday, November 15, 13
  48. 48. ‘Models’ Unlike Ember, Angular doesn’t force you into creating OOP models using their abstractions. Do as you like. But model data should reside in objects that are properties on the $scope (‘model objects’, if you will), not directly in properties of the scope. Operations upon properties stored directly on $scope can have unexpected results. This is *totally* undocumented, but comes from Angular core team. Friday, November 15, 13
  49. 49. WTF is $scope ??? So, if Angular models are just plainold Javascript objects (POJOs), what do we need this $scope thing for? Dependency Injection Angular will the correct, you need it: controllers, use DI to make sure that contextual data is where in re-usable directives & views. $scope also gives us inheritance, via a DOM-like tree. Data available to app root is also available on leaves. Friday, November 15, 13
  50. 50. $rootScope Main/Nav Controller $scope View 1 Controller $scope Directive A-1 $scope Friday, November 15, 13 Directive B $scope Directive C can access all properties from all three parent scopes View 2 Controller $scope Directive A-2 $scope Directive C $scope
  51. 51. Visualizing Scope Use the Angular Batarang!!! Friday, November 15, 13
  52. 52. SERVICES In Detail Friday, November 15, 13
  53. 53. Services in Detail: Why Services? Provide re-usable, testable modular utilities across the application Abstract implementation details, and simply provide a convenient API to other parts of the application. Provide persistent application state across controller, view & directive *instances* Friday, November 15, 13
  54. 54. Services in Detail ‘Back-office’ functions, like networking, event-dispatch, etc. Lazy-loaded singleton modules that persist through the life-cycle of the app, once instantiated. Injected dependencies that can be used by any other module Examples: $http, $log, $location, $route, & services used only by Angular: $provide, $injector, $parse Friday, November 15, 13
  55. 55. Services: A Metaphor In some ways, an Angular Service is little more than a stateful, application-wide controller. Friday, November 15, 13
  56. 56. How are custom Services different from built-ins? They’re not. At all. No, really. (Well, OK: they’re different in naming conventions: don’t use ‘$’ in your custom services.) Friday, November 15, 13
  57. 57. Defining Services There are wayyy too many patterns for defining a service, and the Angular docs fail to even mention the simplest, most intuitive one, using the module’s .service() convenience method (which also aliases to .factory): var app = angular.module('appModule', ['dependency1']); app.service(‘serviceName’, function() { return shinyNewServiceInstance; }); Friday, November 15, 13
  58. 58. Defining Services The older version of service creation, which you’ll still find in the docs, involves the module’s config function and calling .factory (or .service) on $provide: angular.module('appModule',[‘dependency1’]) .config(function($provide) { $provide.factory('serviceName', function() { return shinyNewServiceInstance; }); }); Friday, November 15, 13
  59. 59. So, how crazy complicated is the service instance itself? Friday, November 15, 13
  60. 60. shinyNewServiceInstance Relax! Here, we get to rely on standard JS pragmatics: return either a single function or a revealed module, as you wish allows public & private properties in the constructor Friday, November 15, 13
  61. 61. Single-Function Service angular.module('appModule', [], function($provide) { $provide.factory('notifySvc', function() { var msgs = []; //private variable return function(msg) { //public function msgs.push(msg); if (msgs.length == 3) { alert(msgs.join("n")); msgs = []; } }; }); Just call with notifySvc(msg), after injecting into a controller or directive Friday, November 15, 13
  62. 62. Multi-Property Service angular.module('appModule', []) .service('notifySvc', function() { var msgs = []; //private variable return { submit: function(msg) { msgs.push(msg); }, dump: function() { if (msgs.length == 3) { win.alert(msgs.join("n")); msgs = []; } }; }}); Just call with notifySvc.submit(msg) and notifySvc.dump() Friday, November 15, 13
  63. 63. Service Instantiation Remember: Services are ‘lazy-loaded singletons’. That means the service instance won’t actually be created until you specifically need it. You tell Angular you need it by injecting it into a controller, directive, etc. Friday, November 15, 13
  64. 64. Referencing Services In a directive or controller, you can have direct access to a service and its properties, assuming you have injected it properly. In HTML (an interpolated expression), you can’t reference until you’ve attached it to local $scope. So, in your controller: $ = serviceName.serviceProperty; Friday, November 15, 13
  65. 65. DIRECTIVES In Detail Friday, November 15, 13
  66. 66. What are Directives, Again? Friday, November 15, 13
  67. 67. Friday, November 15, 13
  68. 68. What Are They, Really? 5(-ish) words: Logic & Behavior For UI “...a way to teach HTML new tricks.” Anything in your app that touches DOM Examples: event-handling, behavior management, template pre-processing & insertion, data-binding, ‘Collection Views’, UI Widgets, conditional display, i18n & localization, etc. Friday, November 15, 13
  69. 69. What Are They, Really? The only other Angular construct that really touches the DOM is: Angular Expressions (text only). Filters The rest of it should be in Directives. (Even the ng-view that executes your routing is simply a model-driven directive...) Friday, November 15, 13
  70. 70. What Are They, Really? Structurally speaking, a Directive is just a function that’s attached to an element. But not just a function: a whole execution environment. Really, Directives are mini-applications. You can think of them as little robotic pilots that live on your DOM elements & tell them what to do. Friday, November 15, 13
  71. 71. Friday, November 15, 13
  72. 72. What AREN’T they? Directives. Aren’t. Goes! Just. Please, Where. God: Your. Friday, November 15, 13 JQuery. No.
  73. 73. I BUT... Friday, November 15, 13
  74. 74. Angular isn’t just another way to organize the same old UI code!!! Friday, November 15, 13
  75. 75. Opinionated Principles 1.Declarative, Model-Driven Behavior Friday, November 15, 13
  76. 76. Why Declarative? IMPERATIVE = YOUR PROBLEM DECLARATIVE = SOMEBODY ELSE’S PROBLEM Easier To Read, Maintain: Why scatter event-listeners across 100 linked JS files, then need to go search for them to find out what’s happening on an element. Friday, November 15, 13
  77. 77. Declarativeness ROCKS You’re trying to find handlers for this element: <button id=”1” class=”B C”></button> Well, where are the event-handlers? On ‘#1’? On ‘.B’? ‘.C’? On ‘button’? What if it’s on ‘parentDiv>:firstchild’? You can’t misunderstand what’s happening with declarative directives: <button md-action-handler></button> Friday, November 15, 13
  78. 78. Extending HTML... HTML is NOT a virgin bride or hothouse flower. The Semantics Wars are over. HTML is a highly-abstracted, Object-Oriented language for app interfaces and for *presenting* documents. Docs themselves are increasingly stored in other formats, like markdown. We’re not abandoning accessibility. But it’s not a binary choice, anyway. Friday, November 15, 13
  79. 79. Opinionated Principles 1.Declarative, Model-Driven Behavior 2.Modularity, Reusability across contexts: Write Once, Run Anywhere Friday, November 15, 13
  80. 80. Reusability It’s all about context-awareness, data-binding & DI. Directives know their own element and local scope. You can pass additional data into directives as attributes, right on the element. Friday, November 15, 13
  81. 81. <div id="header_tabs"> <a href="#/home" active-tab="1">HOME</a> <a href="#/finance" active-tab="1">Finance</a> <a href="#/hr" active-tab="1">Human Resources</a> <a href="#/quarterly" active-tab="1">Quarterly</a> </div> AND... <div id="subnav_tabs"> <a href="#/hr/pay" active-tab="2">Pay</a> <a href="#/hr/benefits" active-tab="2">Benefits</a> <a href="#/hr/help" active-tab="2">Help</a> </div> Friday, November 15, 13
  82. 82. Opinionated Principles 1.Declarative, Model-Driven Behavior 2.Modularity, Reusability across contexts: Write Once, Run Anywhere 3.Keep it Local Friday, November 15, 13
  83. 83. No... Friday, November 15, 13
  84. 84. Yes: ‘Local’ Sticks to a self-contained, modular scope, which understands its context: inside the directive, `element` is like `this`. Uses messages, models to affect things elsewhere. Easier to maintain, easier to read, easier to scale. But the challenge to all that is: Friday, November 15, 13
  85. 85. My Awesome Website Needs to Change Things Here Sweet Product Cart: 1 Item(s) $899.99 Buy Now! Product Description: Lorem ipsum dolor sit amet, consectetur adipiscing elit. In erat mauris, faucibus quis pharetra sit amet, pretium ac libero. Etiam vehicula eleifend bibendum. Morbi gravida metus ut sapien condimentum sodales mollis augue sodales. Vestibulum quis quam at sem placerat aliquet. Curabitur a felis at sapien ullamcorper fermentum. Mauris molestie arcu et lectus iaculis sit amet eleifend eros posuere. Fusce nec porta orci. Clicking Here Friday, November 15, 13 Integer vitae neque odio, a sollicitudin lorem. Aenean orci mauris, tristique luctus fermentum eu, feugiat vel massa. Fusce sem
  86. 86. Let’s Build Some! but first... Questions? Friday, November 15, 13
  87. 87. Directive Names Angular uses a convention borrowed from other JS projects: names in HTML are hyphenated... <sample-directive></sample-directive> while identifiers in the JS are camel-cased: .directive(‘sampleDirective’, function(){}) Expect Angular to do this conversion automatically. Don’t fight it. Friday, November 15, 13
  88. 88. How are custom directives different from built-in? They’re not. At all. No, really. (Well, OK: they’re different in naming conventions: don’t use ‘ng-’ in your custom directives.) Friday, November 15, 13
  89. 89. CREATION .directive() is a method we call on an angular.module(), either at creation time or via reference, passing a name and a factory function angular .module('moduleName', ['dependency1', 'dependency2']) .directive('directiveName', factoryFunction() {}) The factory will return either a function or an object containing a function and other settings Friday, November 15, 13
  90. 90. Factories (Note, when we talk about generic ‘factories’, we don’t mean $factory, which is an Angular implementation service.) The factory pattern is all about Functional Programming: using basic Javascript functions to build and return either naiive objects or other functions. Friday, November 15, 13
  91. 91. What do We Do With The Factory Function? Friday, November 15, 13
  92. 92. Two Basic Options: Return a Config Object or a ‘Linking Function’ Friday, November 15, 13
  93. 93. Friday, November 15, 13
  94. 94. Friday, November 15, 13
  95. 95. You’ll See Later, But Ignore For Today: Returning only the Link function Link vs. Compile Pre-Link vs. Post-Link Friday, November 15, 13
  96. 96. Friday, November 15, 13
  97. 97. Using a Config Object angular.module('moduleName'). directive('sampleDirective', function(){ return { link: function(scope, element, attrs) { // this example binds a behavior to the // mouseenter event element.bind("mouseenter", function(){ ... do stuff after mouseenter ... } }, restrict: ‘E’, template: “<div>Hello, World!</div>” }}) Everything but `link` is optional. Friday, November 15, 13
  98. 98. Link Function Args .directive('sampleDirective', function(){ return { link: function(scope, element, attrs) { // this example binds a behavior to the // mouseenter event element.bind("mouseenter", function(){ ... do stuff after mouseenter ... } }, restrict: ‘E’, template: <div>Hello, World!</div> } }) Friday, November 15, 13
  99. 99. Link Function Args 3 standard params for a link function. (Plus optional 4th: controller.) They’re supplied as args by the directive function, if specified. scope: whatever scope object is local element: element declared on: `this` attrs: an object containing the html attributes defined on the element, including the directive invocation itself Supplied to the function not by name but in order. Call them whatever you want. Friday, November 15, 13
  100. 100. jqLite: your path to the DOM Angular will defer to JQuery, if present, but provides its own subset of JQuery for basic DOM tasks. You can’t just use $(), nor find using selectors, unfortunately. But all built-in `element` refs are already pre-wrapped in jqlite object Chain methods as you normally would Friday, November 15, 13
  101. 101. • • • • • • • • • • • • • • • addClass() after() append() attr() bind() children() clone() contents() css() data() eq() find() hasClass() html() next() on() Friday, November 15, 13 • • • • • • • • • • • • • • • • off() parent() prepend() prop() ready() remove() removeAttr() removeClass() removeData() replaceWith() text() toggleClass() triggerHandler() unbind() val() wrap()
  102. 102. Using jqLite (angular.element) .directive('sampleDirective', function(){ return { link: function(scope, element, attrs) { // this example binds a behavior to the // mouseenter event element.bind("mouseenter", function(){ ... do stuff after mouseenter ... } }, restrict: ‘E’, template: <div>Hello, World!</div> }}) $(‘selector’).bind(‘mouseenter’, function() {}) Friday, November 15, 13
  103. 103. ACK! THPPPT!! .bind() is ancient! Where’s .live() ?!? .on() ?!? Friday, November 15, 13
  104. 104. Friday, November 15, 13
  105. 105. A Thought: If angular.element() / jqlite doesn’t support what you’re trying to do... ask yourself: why not? Because they’re lazy bastards? Not so much. Think about other options. Go with the grain, and Angular will reward you. Friday, November 15, 13
  106. 106. Directive Templates Templates can be stored as strings on the `template:` property They can also be loaded from a file, using: `templateUrl: path/to/file/template.html’ Friday, November 15, 13
  107. 107. Templates .directive('sampleDirective', function(){ return { link: function(scope, element, attrs) { // this example binds a behavior to the // mouseenter event element.bind("mouseenter", function(){ ... do stuff after mouseenter ... } }, restrict: ‘E’, template: ‘<div>Hello, World!</div>’ //or: templateUrl: ‘path/to/file.html’ }) Friday, November 15, 13
  108. 108. The Restrict Property .directive('sampleDirective', function(){ return { link: function(scope, element, attrs) { // this example binds a behavior to the // mouseenter event element.bind("mouseenter", function(){ ... do stuff after mouseenter ... } }, restrict: ‘E’, template: <div>Hello, World!</div> } }) Friday, November 15, 13
  109. 109. The Restrict Property Remember that directives are re-usable So, we can restrict the usage of a directive to (a) specific context(s), so that we don’t accidentally try to use it in a situation it wasn’t designed for: ‘E’ = Element ‘A’ = Attribute ‘C’ = Class ‘M’ = Comment Stack as a single string: ‘EACM’. Defaults to ‘A’. Friday, November 15, 13
  110. 110. The Replace Property By default, a directive element will wrap the contents of a template. The `element` object will be the outer directive element. To instead replace the directive element (and object) with the contents of the template, use {replace: true} This is esp critical when declaring as an element... Friday, November 15, 13
  111. 111. Directives DEMO BREAKDOWN 1: Enter-Leave Friday, November 15, 13
  112. 112. So, about that: Model-Driven & Local Directive Design... Friday, November 15, 13
  113. 113. Specifically, the Model-Driven part... Friday, November 15, 13
  114. 114. Why Model-Driven? After all, the imperative approach works fine... ...if you’re omniscient and precognitive. ... and you really, really like refactoring. Friday, November 15, 13
  115. 115. How Can Directives React to Models? With $watch! Friday, November 15, 13
  116. 116. Directives DEMO BREAKDOWN 2: CLOCK (haha! Get it? We’re going to use a clock to demo $watch...) Friday, November 15, 13
  117. 117. Keeping Directive Design Local Friday, November 15, 13
  118. 118. How Can Directives React to Stuff that Happens Far, Far Away? Again, with models & $watch! But sometimes, the inheritance chain isn’t a good solution. For those times... Angular events! $on(), $emit(), $broadcast() Friday, November 15, 13
  119. 119. Advanced Topic: Inter-Scope Communication Use $watch to monitor properties of local $scope or one it inherits from That works great when you only need data to flow in one direction (up) and only on one branch of the tree. What about when you need to go downwards, or sideways? Or a whole bunch of places at once? Friday, November 15, 13
  120. 120. $rootScope ??? Main/Nav Controller $scope ??? View 1 Controller $scope ??? ??? View 2 Controller $scope ??? Directive A-1 $scope Friday, November 15, 13 Directive B $scope Directive A-2 $scope Directive C $scope
  121. 121. Angular Events to The Rescue!!! Just like how a ‘click’ event bubbles up through the DOM tree, you can $emit() an Angular event up the $scope tree, from any starting point. Better than the DOM, you can also $broadcast() an event down the $scope tree. $broadcast()-ing from $rootScope gets you the whole shebang. Friday, November 15, 13
  122. 122. Friday, November 15, 13
  123. 123. Angular Events to The Rescue!!! With events, there’s no need to laboriously climb your way up the $scope tree. You also eliminate the chance of getting the wrong scope. You also get full de-coupling of a controller/directive from a particular place in your app. Use it anywhere, $broadcast() everywhere. Friday, November 15, 13
  124. 124. Angular Events to The Rescue!!! And you don’t even need to predict who all the recipients will be. By sending: $rootScope.$broadcast(‘gameOver’) your whole app gets the information, You can consume the event as many places as you like, with: $scope.$on(‘gameOver’, handlerFunc) Friday, November 15, 13
  125. 125. Directives DEMO BREAKDOWN 3: ActiveTab Friday, November 15, 13
  126. 126. CODA Friday, November 15, 13
  127. 127. 2 Excellent New Tutorials: ng-newsletter’s “Beginner to Expert” series: posts/beginner2experthow_to_start.html Thinkster.IO’s “A Better Way to Learn AngularJS”: pick/GtaQ0oMGIl/a-better-way-tolearn-angularjs Friday, November 15, 13
  128. 128. Must-Use Learning Collection AngularJS-Learning: https:// Friday, November 15, 13
  129. 129. Angular 1.2 New Features migration AngularJS 1.2 and Beyond - YouTube: v=W13qDdJDHp8 (transcript of video, with slides: http:// AngularV1.2AndBeyond_2013-06-11.pdf) Friday, November 15, 13
  130. 130. Angular 1.2 New Features The new animations, in particular, are super-righteous: declare standard CSS animations in classes, then Angular will apply them while migrating content in and out of the DOM. Friday, November 15, 13
  131. 131. Thank You! Friday, November 15, 13