Learning AngularJS articles

From 2014 to 2019, I wrote a newsletter called “Learning AngularJS”. I have collected the articles here as an archive of that newsletter. I also published a video course on testing AngularJS code in 2015.

AngularJS

How to Use Local Storage for Caching in AngularJS 1.6

Window Local Storage is an HTML5 web api that can be used to store data in the browser. The data is stored in a bucket for the current domain name (click here to view the Storage API).

An awesome developer created the angular-local-storage module for AngularJS 1.6 which gives you a nice API to work with in AngularJS for local storage.

What’s cool about is that you can listen for notifications whenever the local storage has been changed (with setItem or removeItem). It also lets you set the storage to use local storage or session storage. Session storage is great for quick caching while local storage is more long-term.

AngularJS API for Local Storage

The API for angular-local-storage is easy to use:

  • isSupported – whether the browser supports local storage
  • setPrefix – prefix used when setting keys
  • getStorageType – the type of storage used
  • set – set a value
  • get – get a value
  • keys – the list of keys that have been set in local storage (very very convenient!)
  • remove – remove a value
  • clearAll – remove all values set
  • bind – binds a value from local storage to a variable in the $scope

The most important API functions for angular local storage are: set, get, and bind.

Here’s an example of how it’s used:

var myApp = angular.module('myApp', ['angular-local-storage']);
myApp.controller('HomeCtrl', ['$scope', 'localStorageService', 'someApiService', function($scope, localStorageService, someApiService) {
  
  function $onInit() {
    console.log('the keys! ' + localStorageService.join(', '));
    console.log('storing a value from an API call');
    someApiService.fetchValues(function(values) {
      localStorageService.set('valuesFetched', values);
    });
    localStorageService.set('formSubmitted', false);
  }

  function submitForm() {
    if (localStorageService.get('formSubmitted')) {
      console.log('form already submitted!');
    } else {
      localStorageService.set('formSubmitted', true);
    }
  }
}]);

In the example you can see that angular local storage is used to fetch values when the controller HomeCtrl is initialized with $onInit. After the value is fetched, we use the localStorage service to set the initial value for formSubmitted.

When the form is submitted through the submitForm method, we check the value of formSubmitted through localStorage and then set its value. The idea is to prevent resubmission of the form. Of course this is just for the frontend and it’s a good idea to check for resubmission on the server backend.

Angular local storage is simple to use and highly valuable as a cache for AngularJS web apps.

The State of Angular 2/4/5+

After the last year of keeping up with Angular 2/4/5+ development, it seems that they’re still gearing up. In my eyes, they have taken on a lot of work and have shifted the ground underneath developers quite a bit. The full adoption and support for TypeScript is welcome news, but there are still many development shops that will use JavaScript and ES6 with Babel. The documentation and examples do not seem to support JavaScript as much as they support TypeScript. This is also true for Dart, which is used by Google for one of the larger Angular projects, but even they cannot count on full support from the Angular team.

There’s also the rapid rate of change. Angular has an upgrade path however it is not fun to upgrade dependencies and change code every few months because the API of the framework has changed.

The state of Angular 2/4/5+ at this point is similar to the state of the Django web framework before it was version 1.0. Before 1.0 of Django, every single week seemed to bring new changes in the codebase. It was fun to be on the cutting edge and the latest and greatest but Django before 1.0 was not ready for production. This cycle is happening to Angular 2/4/5+. If you want to be on the cutting edge, use Angular and be careful when deploying and maintaining a production app.

When should you consider using Angular 2/4/5+?

If you are starting a new project, you should consider Angular 2/4/5+

If you want to develop a mobile app using Angular, use NativeScript with Angular 2./4/5+

If your web development team has at least 3 developers, consider using Angular 2/4/5+

When should you consider using AngularJS 1.6?

If you have an older AngularJS 1.x project, consider upgrading it to AngularJS 1.6 (don’t attempt a rewrite in Angular 2 until you do that!)

If your web development team has 1 to 3 developers, consider AngularJS 1.6 because you will find a lot of modules that have been production-ready and are well-tested. You will be able to ship the project into production and support it for years to come. As I pointed in the last Learning AngularJS issue about Siberian CMS, they are using AngularJS 1.3 for mobile apps and it still works just fine for them.

Thanks for reading!

Thanks for reading! If you’re still using AngularJS 1.6, don’t worry you are not alone, there are thousands of projects out there also using it and the modules are well-tested and production-ready! If you ever wanted to use local storage in AngularJS, now here’s your chance with angular-local-storage.

SiberianCMS: make amazing mobile AngularJS apps

SiberianCMS, a mobile AngularJS CMS, is a content management system. Much like Drupal or WordPress it is easy to manage a lot of content and to produce a mobile app.

Its most unique feature is that it makes mobile apps. The code will compile into a native Android or iOS/iPhone app with all of the content managed by the SiberianCMS backend. If you ever wanted to quickly create a mobile app, this might be the tool for you. I’m considering using it to lower the effort and cost required to create a mobile shopping app and to use it for hackathons.

Mobile AngularJS

As a CMS, SiberianCMS is very easy to use. With SiberianCMS, you can create new forms and pages with a GUI editor, similar to Drupal. It supports custom RSS feeds for adding content as well.

SiberianCMS is very extensible, there are a lot of great plugins/modules for it. Prices for the plugins range from free to over 150 euros. It’s possible for you to create your own plugins and make some money that way.

The plugins/modules for SiberianCMS include:

  • chat/messaging
  • calendar of events
  • classifieds
  • Uber-like taxi-ordering/navigation system
  • maps and directions
  • quizzes and surveys

The cool thing is that these modules are written in JavaScript and as AngularJS components and modules. You can hack on your own module today!

The code for SiberianCMS is open source so you are free to download it and create your own plugins for it. It uses the Open Software License, which is also used by the highly popular ecommerce engine, Magento.

Stable Frontend Mobile/Web Development Is Possible!

What I like, aside from SiberianCMS itself, is that you can build a stable system on AngularJS 1.x. You don’t have to be subjected to the cycle of frontend web framework churn. How many javascript frameworks exist now anyway?

You are able to build solid products for your startup or community or for yourself that can last for years by sticking to one version of AngularJS. For new projects, the choice isn’t between using Angular 2/4+ or AngularJS 1.6. You also have the option to use AngularJS 1.3 or 1.5 or whatever you’re comfortable with. But you should always upgrade.

However. if you want to maintain stability, AngularJS will help you achieve that. I’ve been a big advocate of Angular 2/4+ lately but it is still fun to work with AngularJS 1.x. Also, for new projects I still consider AngularJS 1.x a practical option.

I recommend you check out SiberianCMS for yourself. See how quickly you can prototype and launch a mobile AngularJS app! Maybe try hacking around their source code too.

Upcoming Angular Conferences

Here are a few conferences that are coming up:

  • September 25 to 27, Angular Summit in Boston MA
  • November 7 and 8, Angular Connect in London UK

A Primer on AngularJS Services

The article is by Michael Herman it’s a very nice short article on how to use AngularJS services.

The article talks about what a service is and how to create one. It’s very well done and the code is easy to follow and understand.

When you’re first starting with AngularJS it can be tempting to put a lot of functionality into a controller, but you should be separating concerns and moving some of that functionality into separate services that the controller uses. Even for small apps, it’s good to get into the habit of creating separate services.

As Michael says,

If your controller is handling more than just defining the scope or initial state of your app, connecting your models and views, then it’s are probably doing too much.”

The article is a prime example of great documentation of a core AngularJS feature.

Read the article

See a demo of the code in action.

Unit Testing in AngularJS

The modern way of development is to build and deliver web apps that include automated unit test suites. These automated tests exercise your web app to make sure that it works and doesn’t have any bugs. Tests give you the confident to say to your client or project manager or customer, yes we have the right features and yes they all work.

Test-driven development is a set of techniques that any software engineer can follow, which encourages simple design and test suites that inspire confidence…following these two simple rules can lead us to work much more closely to our potential.

  • Write a failing automated test before you write any code.
  • Remove duplication.
Kent Beck, “Test Driven Development”

Unit Tests

Unit testing is essential and of course, AngularJS lets you do some unit testing. In fact, it was built from the ground-up to co-operate with unit testing by using dependency injection.

One of the better tutorials on fully testing your AngularJS app is Full-Spectrum Testing With AngularJS and Karma.

To begin unit testing AngularJS, you need the following:

  • Karma test runner
  • Jasmine or Mocha/Chai test frameworks
  • Sinon for mocking/spies/stubs

The Karma test runner will run whatever tests you have. The Jasmine test framework lets you define tests and has assertions (such as myValue.is.expected.toBe(3)). Personally, I prefer the Mocha framework since it only defines tests, and lets you use whatever assertion library you want to use such as Chai, it also has lots of nice features.

A classic on unit testing is Test Driven Development: By Example, it’s by Kent Beck who was one of the founders of the Extreme Programming movement.

Mocking Dependencies for Integration and Unit Testing AngularJS

Sometimes when you’re writing a test, you want to make sure that your service or provider is making the right calls to another service. The way to do this is with mocks. Mocks are fake objects that keep track of which methods were called on them.

Mocks are not essential for writing tests, but there are cases where they do help. When you’re writing a controller that connects to your web app’s REST API, you want to make sure that it calls methodX and methodY. By creating a mock service and registering it with AngularJS, you can write a unit test that makes sure those two methods have been called. When using external 3rd party REST APIs, you may want to mock the $httpBackend to make sure the right calls are being made and the correct responses are returned.

Sinon is valuable for defining mocks. It lets you create method stubs and it lets you spy on method calls.

AngularJS Modules:

  • angularjs-nvd3-directives: directives for creating charts and graphs using nvd3.js or d3.js
  • angular-file-upload: directive for handling file uploads using HTML5 when available
  • angular-lorem-image: directive for placeholder ithat uses lorempixel service to generate images

News:

  • Good Practices To Build Your AngularJS App: nice overview of AngularJS with good info on using scopes.
  • AngularJS and scope.$apply: great explanation of how the digest cycle works and how to update data bindings.

AngularJS Meetups:

  • Boston, MA
  • Mountain View, CA
  • New York City, NY
  • Toronto, Canada
  • London, UK
  • AngularJS Conferences

AngularJS Books

Today we’re covering some AngularJS books that can get you started on your path to learning how to design single-page web applications using AngularJS. While the code examples in books can sometimes become outdated, books are still valuable because they go over and explain the major concepts (directives, services, factories, unit testing, etc.) that you need when developing an AngularJS web app.

The guides on the AngularJS website are good starting points but I find that a book can go into much more detail and provide more examples that fully explore each area of the AngularJS framework. Physical books also serve as a nice break from the screen and when written well, they let you mentally figure out what the code examples will do.

“[Mastering Web Application Development with AngularJS] definitely helps a beginner and serves as a handy reference for the experienced developer. Despite having done some work on AngularJS after reading a book and online courses, this book still provided me with so much information […] that I feel I should have picked up this material first.”

— Arun Mahendrakar, 5-star review of Mastering Web Application Development with AngularJS, amazon.com

Pro AngularJS

This book was recently published and has up-to-date code examples. It’s a heavy book and covers everything: directives, services, controllers. It has a nice dedicated section for defining AngularJS services and providers. It’s fantastic.

Here’s an excerpt from Chapter 9 – The Anatomy of an AngularJS App describing dependency injection:

The place to start is to understand the problem DI sets out to solve. Some of the components in an AngularJS application will depend on others. In Listing 9-4, my controller needs to use the $scope component, which allows it to pass data to the view. This is an example of a dependency — my controller depends on the $scope component to perform its work.

Dependency injection simplifies the process of dealing with dependencies — known as resolving a dependency — between components. Without DI, I would have to locate $scope myself somehow, probably using global variables. It would work, but it wouldn’t be as simple as the AngularJS technique.

A component in an AngularJS application declares its dependencies by defining arguments on its factory function whose names match the components it depends on.

As you can see, the explanation is quite clear, perfect for anyone new to AngularJS.

Mastering Web Application Development with AngularJS

This book gives a great overview and walkthrough of major concepts. One thing that’s impressive is that the book has unit tests for every example. Write out the code, write the unit test and run it and you can see exactly what’s going to happen.

What I really like about this book, aside from the extensive unit tests/examples, are the easy to understand explanations of core AngularJS concepts. For example, the $digest cycle and when you need to use the $apply method on scopes. If you understand them, you can improve the performance of your web app and you can avoid common mistakes.

Here’s an excerpt from Chapter 11 – Writing Robust AngularJS Web Applications, page 294:

The idea behind AngularJS model-changes tracking mechanism is based on the observation that at the end of the day, there is a finte (and rather small) number of situations where models can change. Those include:

  • DOM events (user changing value of an input field, clicking on a button to invoke a JavaScript function and so on)
  • XHR responses firing callbacks
  • Browser’s location changes
  • Timers (setTimeout, setInterval) firing the callbacks

Indeed if none of the earlier events take place (user is not interacting with a page, no XHR calls have finished, no timers firing) there is no point in monitoring the model for changes. There is simply nothing going on for a given page, the model isn’t changing, so there is no reason to re-render the DOM.

AngularJS starts its model-observing machinery if and only if it is explicitly told to do so. To bring this sophisticated mechanism to life, we need to execute the $apply method on a scope object.

As you can see, the explanation is clear and the book is full of gems like this.

AngularJS (O’Reilly)

Here’s an example of a good book that has outdated code examples. I would recommend getting this as a reference. This book is a solid reference that explains the major concepts so that you can apply them on your own.

I hope that they release a 2nd edition of the book with updated examples because O’Reilly books are usually pretty good.

Other AngularJS Books:

  • AngularJS in Action
  • Angularjs Web Component Development: Building, Reusing And Exporting Ui Components With Angularjs
  • Instant AngularJS Starter
  • Recipes with Angular.js

AngularJS libraries and modules:

  • ux-datagrid: a highly performant list and data grid, designed for mobile devices.
  • restangular: service that makes creating proper REST APIs easy.
  • angular-translate: add multiple languages and translation to your app.
  • angularfire: use this library to interact with your Firebase backend database.

News:

  • AngularJS support in PhpStorm: autocomplete, custom directives, refactoring, routing and URL template support are now in JetBrains’ wonderful IDE, PhpStorm.
  • AngularJS 2.0: implementation of the next major version is beginning, mobile-first and using ES6 (ECMAScript 6). More modularity is planned and a less complex dependency injection system is being designed.

AngularJS Meetups:

  • Boston, MA
  • Mountain View, CA
  • New York City, NY
  • Toronto, Canada
  • London, UK

Top 15 Awesome Tutorials to Learn AngularJS

AngularJS 1.x is more stable and mature and while Angular has taken off, there are many projects still using AngularJS. It still makes sense for web developers to learn AngularJS. In a few years that may change, but for now, AngularJS 1.x is still a viable alternative to React, Angular 7, Vue.js and Ember and other frontend web frameworks.

If you’re interested in other Angular and AngularJS resources, check out the Learning AngularJS page.

Here are the top 15 awesome tutorials to learn AngularJS:

  1. The Official AngularJS Tutorial
    In this tutorial provided by the team that developed AngularJS, you will learn how to create templates, components, and how to work with two-way data binding. Dependency injection is also introduced in the tutorial.
  2. Year of Moo: AngularJS Guide
    In this guide from Year of Moo (which I’ve linked to before for their unit testing guide for AngularJS), you will learn how to create components and services and how models and directives work. It goes in depth on how modules are created within AngularJS for organization of projects.
  1. Beginning AngularJS in 7 days
    While the website has a lot of ads, the information on it is very good and is a good beginner tutorial for AngularJS. It goes into specifics on how to use REST resources with the $resource module and how to make HTTP requests with $http.

    What I like are the sections on filtering and sorting tables and form validation, two common tasks in web frontends.
  1. Todd Motto’s AngularJS Guide
    Todd Motto is one of the top AngularJS writers and developers. His complete guide to AngularJS is also a good reference when working on a project. It begins with an overview of engineering concepts in JavaScript frameworks, moves on to services and controllers and goes in-depth on routes and the $http and $resource modules.
  1. AngularJS: Getting Started (PluralSight)
    The courses on PluralSight are all very high quality and easy to learn from. They even offer an AngularJS quiz so you can gauge what your own skill level. In this course they show you how to build controllers and directives. In particular it shows how to use the ng-click, ng-repeat, and ng-model directives.
  1. Building a Mobile App with AngularJS 1.6 and Ionic
    In the video course, they cover how to build a mobile web app that can be deployed for iOS and Android using the Ionic framework.
  1. Creating a Quiz with AngularJS
    Test yourself by building a quiz web app with AngularJS! Or just build the quiz app and learn how AngularJS works. What’s nice about this course is that it not only shows you how to build the components and controllers for the app, it also shows you how to style the app and how to move from one screen to another and to carry over data.
  1. Build a GMail clone with AngularJS
    This is always fun, instead of a contrived project to build in order to learn AngularJS, you build a clone of an existing product. This was one of the best ways to teach game programming, making clones of popular games like Tetris or Super Mario World or Final Fantasy.

    In the web development world, making a clone of Instagram (as I’ve done for Elm) or GMail with AngularJS as this course shows you, is an excellent way to learn a frontend web framework.
  1. Creating an app with AngularJS and Rails 4
    In this tutorial, you learn how to create a Rails API that can be used with AngularJS. It shows you how to use the $http HTTP module to make requests to a backend server.
  1. Hands-on AngularJS Tutorial
    This tutorial shows you how to build an online movie booking app with AngularJS. There is a really good section on creating services.
  1. Animate your site with AngularJS
    Animations are important for a smooth user experience, and this tutorial explains how CSS3 animations can be used to enhance your AngularJS app.

    Specifically, it shows you which directives have built-in animation support. Then it ends with walking you through how to create custom animations with JavaScript.
  1. How to create animations with ngAnimate
    This article embeds code snippets of AngularJS so you can see the code in action and modify it and learn from it. It shows you how to animate a list of items, and how to show and hide validation messages for form validation.
  1. AngularJS Routing Using UI-Router
    Routing in an SPA (single page application) is how a URL is translated into the right controller and view to display in the app. For example, a router determines how to route /hello to the HelloController and /world to the WorldController.

    The UI Router is more advanced than the router included with AngularJS which makes it powerful enough to be the default for many AngularJS projects.
  1. Learn AngularJS 1.x Interactively
    CodeAcademy has an interactive way to learn AngularJS where you are given the code for the tutorials, it is explained and you’re free to edit it. The course is nice because it has both free form projects and quizzes to test your knowledge of AngularJS.
  1. AngularJS Data Modeling
    This is an intermediate video course that shows you how to use caching in your models, how to add validation and manage validation through sub-classes.

Angular 5 vs Angular 4 vs Angular 2 vs 1: The complete list

In this article we compare:

  • Angular 5 vs 4
  • Angular 4 vs 2
  • Angular 2 vs 1 (Angular vs AngularJS)

The newest version of Angular 5 is similar but also very different from the previous version of the framework, AngularJS 1.x. This reference page helps you learn the complete list of differences in the Angular javascript web framework. It includes some code examples of the differences and explanations of how they affect your web development with Angular.

IMPORTANT: At the moment, Angular 4 is the LTS version, LTS means Long-Term Support. The latest stable version of Angular is 5 which will continue to evolve. If you are building web apps or mobile apps using Angular, you will want to use Angular 4 because it will be stable in the long-term. You should be able to reliably build and support your Angular 4 app in the future; Angular 5 is more experimental.

Angular 2/4/5+ vs 1

Here’s a giant list of differences and we’re going to explore some of them:

Angular 2 works for more than just JavaScript: it works with TypeScript and Dart too. TypeScript is essentially JavaScript with static typing.

Angular 4 is geared towards TypeScript mainly; the focus of the documentation is on TypeScript rather than Dart or JavaScript. In Angular 4, TypeScript 2.1 and TypeScript 2.2 are supported which gives better type checking in VS Code.

Core modules are more modular, you can use 3rd party modules more easily (great example is the forms module which was separated from the core angular module)

AngularJS 2 has a new syntax for two-way data binding, uses the “banana in a box” syntax which looks like this:

  • Component-based UI, directives in Angular 1 become components in Angular 2, and controllers simply disappear
  • Events use a brand new event syntax, parenthesis around events in attributes
  • Similar to React, properties are passed into components meaning that $scope is removed entirely from AngularJS. In Angular 2 v 1 you will create properties using the @Input decorator/annotation for a component (or directive)
  • Dependency injection is more explicit with decorators/annotations, you can use @Injectable to declare a class that can be injected into other places, and you can use @Inject to declare that a function is dependent on another class
  • Forms in Angular 4 are better structured modules and easier than ever with FormBuilder, FormGroup and Validators built-in
  • Data binding makes implicit references to component variables meaning you can use {{hello}} instead of {{item.hello}}
  • Filters have been renamed to Pipes
  • Uses the let keyword to explicitly define template variables (just like JavaScript ES6’s let?)
  • ng-app has been replaced with Bootstrapping, you explicitly call the bootstrapping method and pass in the module that is the application’s root module, also known as a main entry point
  • CSS classes can be set based on variable bindings with a convenient syntax,
  • ng-hide and ng-show directives no longer exist, you can use the “hidden” property binding to show or hide elements
  • ng-href has been replaced by variable binding
  • Router linking is done with the routerLink property
  • The syntax for using ng-if has changed: *ngIf is the new way to use it
  • ng-repeat has been replaced with *ngFor
  • ng-src has been replaced with binding to the src property
  • ng-style can be used with a convenient syntax
  • The syntax for ng-switch has changed
  • The filter and orderBy filters have disappeared for performance reasons; do any filtering and sorting of data within your components instead
  • The number pipe/filter allows you to set decimal places now and you can use the percent pipe to display percentages data
  • You can use ES6/ES2015 modules!! No need to wrap your modules in IIFE (immediately invoked function expressions)
  • Defining a module’s imports/dependencies and what it exports/provides is far more explicit and less confusing
  • CSS Stylesheets can be linked for specific components using the styleUrls property when defining a component, this makes sure styles aren’t leaking into other components and templates
  • Zones and zones.js are used to keep track of execution context across multiple asynchronous events, making it far easier to reason about the internals of Angular 2 work in contrast to Angular 1 with its scope, digest and watchers
  • Unit tests are easier to write in Angular 2 vs 1 because the rendering layer has been separated and they are faster
  • Mobile web apps are supported with platforms and learn to create mobile/native apps using NativeScript
  • Bower is no longer needed, everything is installed through NPM (Node Package Manager), or yarn if you’re more adventurous
  • The HTTP module uses Rx.js for a Reactive data flow, this replaces promises and is great for realtime data retrieval
  • Reactive programming is used everywhere; it’s used for events, HTTP requests, user input, and more. Data streams replace the $broadcast and $emit and you can create as many data streams as you need
  • Angular 4 has a new animations package for creating smooth animations that give life and motion to your user interface.
  • Below you will find more details about some of these items in the list of Angular 2 and Angular 4 vs AngularJS 1 differences.

Angular 2, Angular 4 , Angular 5 work for more than just JavaScript
Angular 2 works with three languages:

  • TypeScript
  • Dart
  • Vanilla JavaScript (or ES2015/ES6 compiled with webpack to ES5)

The preferred language, at least judging by the API documentation and tutorials, is TypeScript. TypeScript is a language created by Microsoft that includes type annotations and other features, the language compiles down to JavaScript so that it is compatible with all web browsers. Angular 2+ uses annotations (also known as decorators) in TypeScript to make it simple to define components and other commonly used Angular classes such as NgModule and Directive.

There is an excellent article at Infoq on TypeScript and AngularJS 2.

Special Note: JavaScript ES6 is not the preferred language of Angular 2/4/5+, Reference API Docs are targeted towards TypeScript
You will want to use TypeScript instead of JavaScript/ES6 because the Angular team has decided that the core of the language will be written in TypeScript. This means that the best documentation is for TypeScript and that the tutorials and guides will mainly be written for TypeScript. This is not only true for the official/core Angular modules and reference documentation, it’s also true for community blogs and tutorials. Most of the community is using TypeScript.

Special Note #2: Bower Frontend Dependency Manager Has Been Deprecated
Instead of using Bower to manage frontend dependencies for Angular, the best practice now is to use NPM, the Node Package Manager to install Angular modules and libraries. Bower is used for older AngularJS projects but Bower is not used for Angular 2/4/5+ projects.

  • Component-based UI, directives in Angular 1 become components in Angular 2, and controllers simply disappear
    AngularJS 1
    In Angular 1 you would use directives and controllers. They worked but weren’t as elegant as they could be. In Angular 2 vs 1 (and in Angular 4) they decided that controllers are redundant and you can use plain old JavaScript classes instead. This removes the need for $scope and simplifies your unit testing code because when you’re testing a controller, you’re just testing a simple class.

In Angular 2 vs 1 (and Angular 5), directives still exist but there is a specialized version of them called the component. In the majority of your Angular 2 coding you will be using components rather than directives. Components are a sub-class of directives so when you feel the need to use something more powerful and have a special use case, you can use directives instead. For example, the ngFor and ngIf components are actually directives because they have to hook into the life-cycle of a directive.

  • Events use a brand new event syntax in Angular 2 vs 1, learn it
    This was tricky to wrap my head around at first. In Angular 2, when you are binding an event on an HTML element or component, you can use parentheses around the attribute:

Instead of saying “ng-blur”, you can skip that and use “(blur)”.

  • Defining a module’s imports/dependencies and what it exports/provides is far more explicit and less confusing
    In Angular 2 vs 1, the module class ngModule is explicit in defining what it depends on and imports and what it declares for exporting. When you create an ngModule, you will typically be declaring components for export. This allows them to be used in other apps and modules. If you’re writing a module that has a class for API HTTP interaction, your module will depend on the HttpModule (here’s a way to unit test those modules). If you need the angular router, your module will be depending on/importing the RouterModule.

Here’s a more fully-featured example from the Angular 2/4+ API documentation showing what a module declares:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { AwesomePipe } from './awesome.pipe';
import { ContactComponent } from './contact.component';
import { ContactService } from './contact.service';
import { HighlightDirective } from './highlight.directive';
@NgModule({
imports: [ CommonModule, FormsModule ],
declarations: [ ContactComponent, HighlightDirective, AwesomePipe ],
exports: [ ContactComponent ],
providers: [ ContactService ]
})
export class ContactModule { }
  • Mobile web apps with platforms and NativeScript
    You can create native mobile apps using NativeScript. It interfaces with the Angular framework to produce a native app that is as fast as other native apps. The way it does is is through the power of platforms.
  • What are platforms? What is the platform browser?
    • A new feature in Angular 2/4/5+, platforms are interfaces to display and interact with the Angular code. The platform browser is how Angular code is displayed and interacted within the context of a web browser. There are two platform browser options; dynamic platform browser, and platform browser. Dynamic platform browser will compile your Angular code within the browser and then run the web app. The other option, browser platform, relies on you to compile your Angular code which the browser platform will then load and run, it skips the in-browser compilation step entirely resulting in better performance.
    • The mobile platform lets you display and interact with the Angular app through a mobile native app. The mobile platform is provided by NativeScript.

Deconstructing AngularJS Injector

Here’s a deconstruction of injector.js which contains all the functions and classes for dependency injection.

The Perils of Long Explanations and Examples in Comments
Before deconstructing the code, I had to figure out where the actual code was. The reason for this is that AngularJS’s developers tried to be clever and create their own custom documentation system. It looks kinda like JavaDocs, and it will extract the comments into a separate API docs file. The problem is that there is far fewer code in injector.js than comments, and the comments are longer explanations that are more fit for a tutorial or a manual than for a quick API reference, in other words, they belong in the docs/ folder as a text file.

The other problem with these comments is that they’re far away from their corresponding code. For example, there is a comment on the “get” method of $injector from lines 130-140 while the code is at lines 710-725, and line 786 (“get” is an alias for the “getService” method).

The original injector.js is 794 lines of code. When the comments outside of functions are removed, we’re down to 254 lines of code, you can see the result here: https://gist.github.com/omouse/7646610

Contracts or Static Types Would Help
The biggest problem I have with dynamically typed languages is that there are no type hints written out. With AngularJS’s implementation of dependency injection, the dependencies are passed around as the first items in a list followed by the function which dependencies on them. Instead of talking about them as functions (which have no dependency) or arrays where the last item is a function or calling it “array notation”, it would be helpful to create a type that represents them. Not a class, but a type. This would give it a name and make it easier to refer to.

Alternatively, contracts could be written for functions and methods that would state how to make a valid call to a function.

Being able to state function(x,y) requires that x is an Object that has the method “helloWorld” would be fantastic. It would save a lot of time reading through code. I know that not everyone does this, but Angular, at least in injector.js, is fond of creating objects that are plain Objects that don’t inherit or extend from other classes.

I guess this is why unit tests exist, but I find stating the contract right where the code is to be far more useful than referring back and forth between the code and the unit tests.

I’ll give an example here of what I mean:

function hello(name: String): void {
console.log(‘Hello ‘ + name + ‘!’);
}

function factory(name: String, factoryFn: Function): FactoryObject {
// …
}

function provider(name: String, provider_: FactoryObject or DIFunction): FactoryObject or DIFunction {
// provider_ is an object or a function that
/ uses dependency injection notation
}
Where the type FactoryObject is defined as an object that contains the $get method, and the DIFunction type is just a function or a list where the last item is a function. It would be much clearer to me to see what’s expected when using a function.

Anyway, let’s get to the deconstruction of injector.js…

Deconstruction: injector.js
Function: $injectorMinErr
Line 45 defines a new function using minErr called “$injectorMinErr”, the function returns an Error. The “$injector” argument is used as a prefix when errors are thrown. At line 593, in “createInjector”, the “$injectorMinErr” function is called, the arguments are: the type of error, the format string, and anything after that are variables to use in the format string. The format string uses {0}, {1}, … {N} for substituting variables. You can view the docs and code for minErr here.

Function: annotate
Lines 41-44 are used by the “annotate” function (line 46). They’re regexps, regular expressions.

FN_ARGS searches for a multi-line string that matches the text “function” and has a match group for function arguments. For example, it would match “function hello(first_name, last_name) { … }”, and the match would be “first_name, last_name”.

FN_ARG_SPLIT is used to split the arguments list into separate arguments, as an example, “first_name, last_name” would be split into the array [“first_name”, “last_name”].

FN_ARG has two match groups, one for the underscore and the other for the rest of the name of the argument. For example, for “param” the match groups would be “” and “param”.

Line 46-74 is the “annotate” function. The only argument it accepts is “fn”, a function or an array. It returns a list of dependencies, stored in the local variable $inject.

If “fn” is a function, we check to see if it has dependencies stored in “fn.$inject” as a list, at line 53. If the dependencies aren’t already stored, some cleverness happens. When “toString” is called on a function, the code for the function is returned and the code itself is anazlyed. The function name and arguments are extracted straight from the string representation of the function, using the previously defined FN_ARGS, FN_ARG_SPLIT, FN_ARG and STRIP_COMMENTS (lines 56-59). The arguments have any leading underscore removed (using FN_ARG). All function arguments are pushed into the dependency list, $inject.

Lines 66-72, if an array or other object is passed in, it uses “assertArgFn” to ensure that “fn” uses the array notation for a function, where last item in the array is a function, and the arguments up until the last argument are dependencies that need to be injected. If “fn” is some other object, an error is thrown by “assertArgFn”. If the array is valid, the items 1 to N-1 are stored in $inject, at line 69.

Function: createInjector
Line 576 defines the createInjector function. It accepts one argument, “modulesToLoad” which is an array of module names to load. It returns “instanceInjector” which is an object returned from the “createInternalInjector” function.

Line 580, the modules that have been loaded are stored in “loadedModules”. These are

The createInjector function has quite a few internally defined functions, the power of closures and first-class functions at work.

These internal functions are:

  • supportObject(delegate)
  • provider(name, provider_)
  • factory(name, factoryFn)
  • service(name, constructor)
  • value(name, val)
  • constant(name, value)
  • decorator(serviceName, decorFn)
  • loadModules(modulesToLoad)
  • createInternalInjector(cache, factory)

Lines 581-590, the “providerCache” is created with a single property, $provide which contains references to various internal functions.

In line 595, the “instanceCache” is created.

Lines 591-594, the “providerInjector” is created and set as the providerCache’s $injector property. The factory method passed to “createInternalInjector” throws an error if the provider doesn’t already exist in the cache.

Contrast this with lines 596-600, the “instanceInjector” is created and set as the instanceCache’s $injector property. The factory method passed to “createInternalInjector” retrieves an existing provider (using the providerInjector’s get method) and then returns an instance created using the provider’s $get method (line 599).

Line 603, we’re looping through each module in “modulesToLoad” and using the the instanceInjector to invoke each module function.

We’ll go through the internal functions in order.

createInjector.supportObject

Line 611, the “supportObject” internal function accepts a function as an argument, “delegate”. The “supportObject” function is currying, it returns a function which accepts two arguments, key and value. When key is an object (see isObject), it loops through each property key/value (using forEach and reverseParams) of the object and calls the “delegate” function with the property key and value.

Otherwise, the key isn’t an Object and we pass the key and value argument to the “delegate” function.

Example:

function myDelegate(key, value) {
console.log('myDelegate, ' + key + ': ' + value);
}
var mySupportFunc = supportObject(myDelegate);

mySupportFunc('some key', 'some value'); // this will call myDelegate('some key', 'some value')
// the next call will loop over the keys/values and pass them to myDelegate
mySupportFunc({
'a': 1,
'b': 3,
'c': 5
});
// is the same as:
// myDelegate('a', 1);
// myDelegate('b', 3);
// myDelegate('c', 5);

createInjector.provider

Line 621, the “provider” internal function accepts two arguments, “name” and “provider_”. “Name” is a string, while “provider_” is either a function, an array, or a Provider object. When “provider_” is an array it’s actually a function with dependencies and uses dependency injection (lines 623-624). If it’s a Provider object, then it needs a “$get” factory method (lines 626-627).

Line 622 ensures that the “name” doesn’t have a “service” property set.

The “provider” function adds the “provider_” to the provider cache and returns the now-cached provider, line 629.

createInjector.factory

Line 632, the “factory” internal function accepts a “name” and a “factoryFn”. “Name” is a string, while “factoryFn” is a factory function. The function calls “provider” and passes both arguments to it (the factory function is used as the “$get” property of a new object).

createInjector.service

Line 634, the “service” internal function accepts a “name” and “constructor”. It returns the the result of calling the “factory” internal function, passing “name” and a factory function (a function with dependencies) to it. The factory function depends on the $injector and passes the “constructor” function to $injector.instantiate (defined on line 770, part of the object returned from createInternalInjector).

createInjector.value

Line 640, the “value” internal function returns the result of calling the “factory” internal function, passing in the “name” (a string) and the “val”. The “val” argument is wrapped in “valueFn” which returns a function that returns the given value, see line 383 in Angular.js.

Here’s an example of how to use valueFn:

// valueFn(value)
var getNumber = valueFn(3);
console.log(getNumber()); // prints 3 on the console

var getName = valueFn('Some name');
console.log(getName());

// getName could have been defined as:
// function getName() {
// return 'Some name';
// }

and here’s how the “value” internal function works:
var myValueFactory = value('hello', 'world');
// Evaluation/trace of the call to "value":
// value('hello', 'world')
// => factory('hello', valueFn('world'))
// => factory('hello', function() { return 'world'; })
// => provider('hello', {
// $get: function() { return 'world'; }
// })
// => { $get: function() { return 'world'; }
console.log(myValueFactory.$get()); // prints 'world'

createInjector.constant

Line 642, the “constant” internal function takes two arguments, “name” and “value”. It stores the “value” in the $injector’s providerCache and the instanceCache. The “name” argument should be a string, while the “value” can be any type of object.

createInjector.decorator

Line 648, the “decorator” internal function takes two arguments, “serviceName” and “decorFn”. The “serviceName” is a string, it’s joined/concatenated with the providerSuffix so that the provider can be retrieved from the providerInjector (line 649). The $get method of the provider is stored (line 650), so that it can be decorated (similar to how Python decorators work) in lines 652-654. The instanceInjector and its “invoke” method is used (defined later on, line 727). The decorated $get function returns the result of invoking the decorator function, “decorFn” with the original $get method passed in as a $delegate to “invoke”.

createInjector.loadModules

Line 661-702 defines the “loadModules” internal function. It accepts one argument, an array of modules to load. It loops through each item in the array, and if it’s a string it uses angularModule to find the existing module function to load. It also finds all of the modules that the module requires (stored in the “requires” property), lines 668-677. If the item is a function or array (a function with dependencies), there’s no need to search for an existing module, it’s used as is.

The checks for each item are wrapped in a try-catch block which throws an error (using the $injectorMinErr function) that displays the stack trace, lines 685-698.

createInjector.createInternalInjector

Finally we get to the good stuff, line 708 to the end of the file, the function that actually creates an injector (at least internally). The function accepts a cache object and a factory function.

It contains the following inner functions:

  • getService(serviceName)
  • invoke(fn, self, locals)
  • instantiate(Type, locals)

createInternalInjector.getService

Lines 710-725, the “getService” function returns a service from the cache passed to createInternalInjector. If the service doesn’t exist yet, the factory function passed to createInternalInjector is used to create the service and the cache is updated.

Learning AngularJS Testing video course

In 2015, I published the course “Learning AngularJS Testing” for Packt Publishing. In 2016, it was available on O’Reilly, Udemy (over 100 students) and Lynda.com (over 8000 views).

Table of Contents

  • Setting up AngularJS for Unit Testing and End2EndTesting
    • The Course Overview
    • Setting up Karma and Jasmine with Grunt Task Runner
    • Setting up the Project Structure
    • Configuring Karma for Testing
  • Testing Controllers
    • Testing Controllers That Have No Dependencies
    • Testing Controllers That Have a Dependency
    • End2End Testing Two Controllers
  • Testing Directives
    • Creating an Accordion Directive
    • Unit Testing the Accordion Directive
    • An End-to-End Test of the Controller That Uses the Accordion Directive
  • Testing $resource-based REST API Services
    • Creating and Testing the $resource Service Using Mocks and Spies
    • Creating a REST API NodeJS Server with Fake Data
    • Displaying Information with a Directive (from the Service)
    • Displaying Information with a Controller

Course Description

Learning Angular.JS Testing will help you to understand the different aspects involved in testing components, such as controllers and directives, with the help of a practical pizza ordering application right from the start, all the way to the end!

We’ll start by constructing a project structure of our app, before installing and initializing various helpful tools such as Karma, Jasmine, and Grunt. We will create controllers for ordering the pizza, reviewing the order and test them be it with or without any dependencies. Not only that, but we will also go through testing the navigation between two controllers with the help of End2End testing. After that, we will create accordion directives for our application, unit test them, and resolve the errors if these tests fail. Furthermore, we will modify our services to use the $resource module and help them interact with REST API web services, as well as unit test them with the help of mocks and spies. Finally, we will create and test directives and controllers which fetch information from the service and display it.

At the end of the course, you’ll be familiar with the various approaches involved in testing AngularJS code and will be able to implement them to develop bug-free and maintainable applications.