4 min read

Some AngularJS notes

I wanted to brush up on my AngularJS over the last few days and I found some of my old notes - thought someone else may find them useful.

AngularJS introduction / notes

Key

Facts / description
“Angular way” / Advice
My judgement calls

Angular concepts

Scope

  • Scope is the data model.
  • Nested (like the DOM).
  • Updates to scope are immediate.
  • Forget Rails/ Django etc scope, its not like that.
  • Scope just links things together (like UI and Data).

Controllers

  • Typically represent a page in an application.
    • Destroyed when navigating away
  • Controller should prepare the scope.
  • May be nested.
  • Whenever possible delegate all the logic out of the controler - thin controler = better.
  • Avoid DOM manipulation inside of them (use directives instead)
  • May have a template(s) associated.
  • e.g.
    • Set Info controller (describe page)
    • Set Media controller (upload/reorder/dragdrop)
    • Set Caption controller (caption page)

Templates

  • Can be partials (can include other templates)
  • Can have some logic bits in them like if, foreach (but don’t go nuts)
  • Can be inline or loaded via AJAX
  • e.g.
    • header + nav region
    • set info page
    • partial media item display

Directives

  • Self contained “packages” that act on the DOM.
  • Think of them either as widgets or widget enhancer.
  • May be nested.
  • Can include other bits of code (e.g. jQuery lib).
  • Advanced crap (could be we don’t get this yet) :
    • Can have an associated controller inside of it (for complex stuff)
    • Can also have a controller along side it too (directive-controller)
  • **Can communicate with parent scopes **
  • They are instantiated in the template by using tags
  • e.g.
    • Drag and drop enhancer
    • Char limit enhancer

Directive and Scope binding

  • Demo code to help with understanding : http://plnkr.co/edit/nRnAhMMb5Kjr1ZwpIr7W
  • You have 3 options @, & and =
  • = (Two way binding)
    • Magic and powerful
    • This means, the my-directive-var is actually a pointer to the ngModel called name. That ngModel is then passed by reference into the directive.
    • So, $scope.myDirectiveVar => ng-model="name" = OliverOriginal and so changes to$scope.myDirectiveVar are actually changes to ng-model=name.
    • Go ahead and test the demo : http://plnkr.co/edit/nRnAhMMb5Kjr1ZwpIr7W
    • You can edit ether input box and the other will update - cool eh?
  • & (One way binding)
    • This means, the my-directive-var is actually a pointer to the ngModel called name. That ngModel is then passed by value into the directive.
    • So, $scope.myDirectiveVar => ng-model="name" = OliverOriginal (just like in the “=” two way binding), but, changes to each are not reflected in the other.
    • If you set $scope.myDirectiveVar = 'DaveDirective' in the link function (see comment in the demo), it will get set only inside the directive, parent unchanged.
    • Any changes will also be local only.
  • @ (Text binding)
    • This means, the my-directive-var value name will have been “passed by value” into the directive.
    • So {myDirectiveVar} = name.
    • But. $scope.myDirectiveVar == undefined (* except if you use watch, see bellow).
    • Any changes made, as its by value, are local only.
    • Always a string.
    • Parsed (so {{}} stuff will work).
    • Expected only to be used with templates
    • Not simply accessed/edited inside the directives link function, as its not yet interpolated (happens later in the loop)
    • You CAN get access to the result, but requires use of the $watch function e.g. $scope.$watch(‘myDirectiveVar’, function() {
      console.log($scope.myDirectiveVar); $scope.myDirectiveVar = 'WilliamWatcher’; });

Modules

  • Modules in Angular are different ways of encapsulating data and logic
  • Services, Factories and Providers
  • There are two phases in the run cycle:
    • Configuration: when the application boots
    • Injection: when the module is created inside a controller that requests it

Services (object)

  • Act as singletons (not destroyed between pages)
  • Used to hold active data or provide functionality across the app
  • No constructor arguments, injecting a service returns an object
  • Useful for static data, like {a:1, b:2}
  • e.g.
    • In current uploader: Set Service = Stores (and transmits) set information (title etc)
    • In current uploader: Util Service = IPTC extraction, Thumbnail generation, etc
    • Forward: General purpose code
    • UUID - to generate uuids
    • Util - for thumb generation etc
    • When possible we should attempt to use Providers

Factory (a function that returns objects)

  • Like services but provide a “constructor” with arguments
  • Injecting it returns a function that creates services
  • They are not shared between controllers
  • Useful when you need to do ‘new Object()’
  • e.g.
    • While this can be used for modules that require some sort of parameters (like Piwik which requires username and site-id) we should attempt to only use Providers

Provider (an abstract factory with config)

  • The only major (and very important) difference is that they can be configured before they are injected. This is really useful for testing.
  • This allows to have every provider configured (api url, test url, api keys, permissions etc) before it is being used in a controller
  • Allows the separation of config and code
  • e.g.
    • We should use providers instead of factories in almost all cases.
    • We can use build Domain specific services as well as for stubbing/testing
    • Set service with domain based validation and required field settings
    • Any module that requires any type of configuration

Filters

  • Transform data in templates
  • Used for formatting data on screen
  • e.g.
    • epoch converter
    • length trimmer + …
    • File size converter

More reading and notes

Personal preferances

Skinny controllers

  • Try to keep them small and simple
  • Controllers are likely to be more domain specific than any other part of the app (so less code here the better)
  • Most of the application logic should be encapsulated into directives and modules