Notes on AngularJS


Most of AngularJS is straightforward and there’s good documentation elsewhere online.

Some important/interesting bits 

  • filters are very cool e.g. {{ lastname | uppercase }}. Particularly useful with ng-repeat e.g. ng-repeat="x in names | orderBy:'country'" or ng-repeat="x in names | filter : 'i'" . Wham! So convenient. And you can write your own filters.
  • ng-src for images
  • ng-bind is one-way binding ($scope to view); ng-model is two-way binding.
  • easy form validation with using the required attribute, .$valid or .$error​, and possibly some cool CSS magic using ng-dirty/pristine/valid/invalid. Good to disable default browser (novalidate) validation to have consistency.
  • when working with tables, there are handy properties like $odd , $even, $index you can use, say, with ng-if
  • creating dropdown lists connected to a model is easy with ng-options (while you could also use ng-repeat, with ng-options the objects don’t have to be strings)
<select ng-model="selectedName" ng-options="x for x in names">
// or using any Object, where x is the key, y is the value.
<select ng-model="selectedCar" ng-options="x for (x, y) in cars">
  • angular events could be used for some pretty cool stuff with animation
  • ng-include lets you refactor out snippets of html, which is loaded via ajax
  • consider using a custom directive instead of ng-include – makes the HTML more expressive.
  • custom directives can be of type element, attribute, class, or comment. Default is element and attribute (i.e. restrict: 'EA').
  • you can move controller logic into a custom directive using the returned object’s controller property.
app.directive("productDetails", function() {
   return {
      restrict: 'E',
      templateUrl: 'product-details.html',
      controller: function(..){/*controller logic can be moved here*/},
      controllerAs: 'someAlias'
  • $scope belongs to the controller, $rootScope is for the whole app.
  • while ng-init lets you initialize some values, should really think whether this initialization belongs in a controller.
  • there are angular equivalents (as services that start with $) of native things like window and location – and it’s best practice to use these angular services. You can write your own services.
app.service('hexafy', function() {
   this.myFunc = function (x) {
      return x.toString(16);
  • cannot call this inside the success call on $http service to refer to the containing controller’s this. Makes sense.
  • angular handles asynchronicity using promises (so no callback hell).
  • config(..) runs before run(..), which runs before controller(..).
  • remember to use closure for javascript modules, good practice.

Thinking about MVC and TDD in AngularJS

AngularJS lends itself very well to an MVC approach.

Keep the view stuff in the HTML, the controller logic in .controller(..)s, and the model (likely tied to a backend service/database) in variables in the angular module (bound to the view with the intention of exposing the minimum information needed).

Split view/controller/model components so that each model entity (e.g. product) corresponds to isolated controller(s) (e.g. productController), and view snippets (e.g. productsList HTML element or custom directive).

This way each component has a small focus of what it is trying to do and it can do it well. This also makes it easier to test-drive the application, small careful steps.

Modularity and testability can be further improved by using proper Angular services (e.g. $window, ​$location instead of the native elements). Using dependency injection, you can inject mock objects and check that the methods you expect are being called on the injected (mock) services in unit tests.