NativeScript: Edge of Tomorrow


This article is all about my experiences of building a Native Android application using NativeScript. NativeScript a framework for building cross-platform Android & iOS apps using Javascript and XML. For the reference, I am in the middle of migrating the same application to NativeScript + Angular combo (just for fun) as it leverages existing Angular skillset such as data-binding, event handling, routing, AuthGuard, etc, and makes it easy to reason about as well.

In a nutshell, NativeScript is not just a set of Javascript libraries but more of a runtime that enables to call Native Android and iOS apis using Javascript. It uses a Javascript virtual machine – V8 for Android and Webkit Core for iOS – that interprets and executes Javascript code at runtime to their respective native code. Hence, there is no limit in terms of which native API can be called in NativeScript, makes it a super powerful tool – worth adding in your arsenal πŸ™‚

This article does not discuss about building Native apps in NativeScript because their documentation is pretty neat and covers it all.

Android ecosystem

Even though you were convinced to write native apps in pure Javascript, that fact is partially true. Meaning you still need to setup android SDK and tools in order to run your application on Emulator or Device. Oh boy, it was PITA in the beginning, especially when you are used to write for Web only – just Write. Refresh. Repeat!

One of such issues faced even before I could run their Sample Groceries app was the ANDROID_HOME environment variable is not set error, while running tns platform add android command. Although, there were tons of stack-overflow answers about that weirdo behavior but unfortunately all were suggesting to add ANDROID_HOME to the PATH environment variable – been there, done that already. At one point, I had decided to give up on NativeScript as I was this frustrated!

But soon the NativeScript community slack channel came to the rescue which I found on their troubleshooting documentation. That culprit is sudo – was running sudo tns platform add android like a rookie πŸ‘Š. Nonetheless, I quickly got over it and set up the project with tns create FreshCall command.

NativeScript Plugins

The android application named FreshCall that I was building is a simple phone call management app to keep a tap on number of users being called on a daily/weekly basis, extract call charges for reimbursement purposes, and possibly record a phone conversation (with speakers on) for quality purposes. As you have already guessed that the application supposed to use android native APIs for most of the requirements such as ask permissions, choose or dial contact numbers, record conversation and upload it to Firebase, fetch call charges from USSD dialogs, etc. Luckily, the NativeScript community is flourished enough to have many plugins ready for most of the things I needed 😊

I realized that building traditional apps in NativeScript is far more easier than ones using native APIs. That’s why problems and worries did not stop for me at the rookie mistake made earlier, after all it was just the beginning.

Migrate Android code to NativeScript

Obvious thing for any phone management application is to detect Incoming calls and allow to make Outgoing calls using TelephonyManager. Truck load of articles and stack-overflow questions can be found on the topic, however, using them in NativeScript was a big deal. But Extending native classes section from the NativeScript documentation was quite useful that opened up ways for further exploration.

Below is the incoming call tracking code in Java (android):

private class CallStateListener extends PhoneStateListener {
  @Override
  public void onCallStateChanged(int state, String incomingNumber) {

  }
}
tm = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE);
tm.listen(callStateListener, PhoneStateListener.LISTEN_CALL_STATE);

So the above Java code can be ported to NativeScript as follows:

var callStateListener = android.telephony.PhoneStateListener.extend({
onCallStateChanged: function (state, incomingNumber) {

}
var application = require("application");
var tm = application.android.context.getSystemService(android.content.Context.TELEPHONY_SERVICE);
tm.listen(new callStateListener(), android.telephony.PhoneStateListener.LISTEN_CALL_STATE);

How did I manage to port it so flawlessly? Here is a simple trick:

  1. Learn to extend android native classes in NativeScript.
  2. Search android documentation for a native property such as PhoneStateListener and refer the java.lang.Object path for the same i.e. android.telephony.PhoneStateListener.

The similar trick is applicable for application ctx, android Context, and tm.listen event.

Background Services

NativeScript community is so kind to give you all the tools to build a bridge, but the only condition is that you’ve to learn to build it yourself, πŸ˜„. I hope one day it will be a piece of cake as NativeScript grows and will be widely adopted as a standard to build native apps.

To track the USSD dialog’s response – the call charge window appears after the call ends – I needed a background service to keep an eye on it and extract the the call charge as soon as it shows up. Somehow I could write a background service myself with the help of the sample provided by NativeScript community and port the USSD parsing using the trick we just learned. However, the onServiceConnected() method – enables accessibility service to read USSD responses – was not getting registered even after enabling it for the application from the android settings.

During the salvation of this problem, I learned two things:

  1. When in doubt, always rebuild using tns build android (remove the existing application from the device before live-syncing again).
  2. Reinstall android packages if updates are available.
    Android SDK and tools
    Android SDK and tools

Wrap up

Experience of building the android application (without having any knowledge of Native Application Development before) was terribly empowering πŸ˜‰. My advice to fellow developers is to keep Android Documentation open all the time!

Peter Kanev from NativeScript core team had been a great help. Also, special thanks to Brad Martin (who built many plugins I’ve been using) and Marek Maszay for their constant support and cheer on Slack.

Live on the Edge Of Tomorrow today with NativeScript!

Cautionary tale for Experts


Imagine a beginner (who has come from a decent front-end background) asking not-so-dumb questions to an expert in the field of Native application development. I hate the term “expert” because no one is purely expert in this field – every person is learning something new from others on a daily basis. But I’m quoting the term for the sake of the article. Here is how the conversation went:

Beginner: Is there a way to find an SDK version like we do with JS library?

Expert: What a dumb question! You do not understand native development that’s why you are asking it.

Beginner: Actually documentation does not have that details, hence asked.

Expert: Have you ever coded in Android/Java??

Beginner: Nope. Will I automatically get the new version of the SDK or have to update the manifest file each time?

Expert: Yes, automatic update!

Beginner: So I do not even have to run some sort of build command to pull in the new version like npm update does.

Expert: Please don’t over analyze the things that you don’t understand or don’t know. It wastes your as well as my time πŸ™‚

Beginner: I’m not over analyzing, just trying to understand by comparing it with frontend development, but you can be little gentle solving such queries raised by the beginner like me.


As you can see the expert was trying to be arrogant by his knowledge and skills. To me it were acceptable if and only if he/she would have resolved my queries. Unfortunately, he/she had not answered any query in a sane way though. Una Kravets‘s recent tweet speaks about the same issue:

Through this post I just want to advice all the experts that,

Whatever high-skilled wits you’ve acquired were based on documentation, manuals, books, and articles written by someone else. You would not be the expert today if those experts had disparaged you like that. All the experts owe it to those they have learned from and the only thing to pay back the favor is by sharing your knowledge to the next generation without being cocky.

Remember, Sharing your knowledge with others does not make you less important.

Angular2: Data Binding


In the previous article, we had explored how dependency injection works in Angular2 compared to Angular1. In this article, I will walk you through the one-way vs two way data binding and how its different but quite similar in Angular2.

Angular1

As usual, we’ll quickly go through the Angular1 example. Let’s take a simple example (HTML) from my free ebook on Angular1 Directives that explores how data binding works in Angular1. Notice we have not written a single line of Javascript code to enable the data binding in the following example:

<html ng-app="App">
<head>
  <title>Two way Data Binding with Form Controls</title>
  <script src="../bower_components/angular/angular.js"></script>
</head>
<body>
  <input type='checkbox' ng-model='choose' />
  <div>{{choose}}</div>

  <button ng-click="choose=!choose">Toggle Checkbox</button>

  <script type="text/javascript">
    angular.module('App', []);
  </script>
</body>
</html>

Now that we’ve a working demo, let us migrate it to Angular2.

Angular2

Let us create a typescript file twoway-binding.ts first to lay our main component.

import { NgModule, Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

@Component({
  selector: 'ng-app',
  template: `
    <input type='checkbox' [(ngModel)]='choose' />
    <div>{{choose}}</div>
    <button (click)="choose=!choose">Toggle Checkbox</button>
  `
})
export class DataBindingComponent {
  choose: boolean = true;
}

@NgModule({
  declarations: [DataBindingComponent],
  imports:      [BrowserModule, FormsModule],
  bootstrap:    [DataBindingComponent]
})
export default class MyAppModule {}

platformBrowserDynamic().bootstrapModule(MyAppModule);

We are already familiar with Component, ES6 Class, bootstrap, etc. jargons from the first article as those are the backbone of Angular2. The only difference here is the template with data-binding expressions.

In Angular1, the two-way data binding was enabled by default, for one-way data binding the expression should be wrapped in {{choose}}. Also the attribute name supposed to be hyphenated. However, in Angular2 the attribute should be in camel-case with subtle differences that affect the way data flows:

  1. [Component -> Template]
    To show a model in a template which was defined in the component, use square-bracket or double-curly syntax a.k.a. One Way Binding.
  2. (Template -> Component)
    To broadcast an event from a template in order to update the model in the component, use round-bracket syntax a.k.a. One Way Binding.
  3. [(Component -> Template -> Component)]
    To have both behaviors simultaneously, use round-bracket inside square-bracket (or banana-in-the-box) syntax a.k.a. Two Way Binding.

This clearly means that the two-way binding in Angular2 is opt-in and can be enabled by importing BrowserModule to plug it in the NgModule.

In the above example, we want to toggle the expression choose from the template to the component using (click) when the button is clicked and update the checkbox in the template immediately using [ngModel]="choose". We also want to update the model choose in the component if the checkbox is toggled manually using [(ngModel)]="choose". Do not get confused with one-time binding in Angular1 i.e. {{::choose}} where the model used to be freezed once evaluated, there is no such thing in Angular2.

Now let us update HTML markup as usual.

<html>
<head>
  <title>Angular2: Two way Data Binding with Form Controls</title>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <!-- 1. Load libraries -->
  <script src="../node_modules/core-js/client/shim.min.js"></script>
  <script src="../node_modules/zone.js/dist/zone.js"></script>
  <script src="../node_modules/reflect-metadata/Reflect.js"></script>
  <script src="../node_modules/systemjs/dist/system.src.js"></script>

  <!-- 2. Configure SystemJS -->
  <script src="../systemjs.config.js"></script>
  <script>
    System.import('ch01/twoway-binding').catch(function(err){ console.error(err); });
  </script>
</head>
<body>
  <!-- 3. Display the application -->
  <ng-app>Loading...</ng-app>
</body>
</html>

Wrap up

Remember, because of the simplified template syntax in Angular2, you can do lot of things easily such as,

  • {{textContent}} becomes [textContent]="textContent"
  • ng-bind-html="html" becomes [innerHTML]="html"
  • ng-mouseup="onMouseUp()" becomes (mouseup)="mouseUp()"
  • my-custom-event="fire()" becomes (customEvent)="fire()"

Fewer templating syntax means Faster learning! Head over to a live data binding in action.

Angular2: Dependency Injection


In the last article, we’ve explored basic differences between Angular 1 and 2 with respect to Component over Directive, TypeScript over ES5, ES6 Class over Controller, and Decorators/Annotations. We’ve pretty much got acquainted with setting up Angular2 in TypeScript with SystemJS to begin our journey with Angular2 in coming weeks. In this article, we’ll investigate how dependency injection that we always loved is different in Angular2 than Angular1. We are not going to cover what dependency injection is in this article though, so if you are not familiar with it yet, follow the documentation for more information.

Angular1

As usual, we’ll quickly go through the Angular1 example. Let’s take a simple example (HTML and JS) from my free ebook on Angular1 Directives that explores how DI works in Angular1. Notice we’ve used ngController directive in which we are going to inject a custom service. Also stare at ngApp directive which was a recommended way to bootstrap an application automatically in Angular1 rather than manually using angular.bootstrap method.

<html ng-app="DI">
<head>
  <title>AngularJS: DI</title>
  <script src="../bower_components/angular/angular.js"></script>
  <script src="../js/ch01/di.js"></script>
</head>
<body ng-controller="SayHi">

<h1>Check the console</h1>

</body>
</html>

Here is the JavaScript code for the above example. We have defined the custom service named Hello and later injected the same into the controller called SayHi.

var App = angular.module('DI', []);
App.service('Hello', function() {
  var self = this;
  self.greet = function(who) { 
    self.name = 'Hello ' + who;
  }
});

App.controller('SayHi', function(Hello) {
  Hello.greet('AngularJS');
  console.log(Hello.name);
});

Now that we’ve our demo up and running, it’s time to migrate it to Angular2.

Angular2

Let us first update the JS code first and walk through the changes.

import { NgModule, Component, Injectable } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

@Injectable()
class HelloService {
  name: string;
  
  greet(who) {
    this.name = 'Hello ' + who;  
  }  
}

@Component({
  selector: 'ng-app',
  template: '<h1>Check the console</h1>'
})
export class DIComponent {
  constructor(public Hello: HelloService) {
    this.Hello.greet('Angular2');
    console.log(this.Hello.name);
  }
}

@NgModule({
  declarations: [DIComponent],
  imports:      [BrowserModule],
  providers:    [HelloService],
  bootstrap:    [DIComponent]
})
export default class MyAppModule {}

platformBrowserDynamic().bootstrapModule(MyAppModule);

We are already familiar with Component, ES6 Class, bootstrap, etc. jargons from the previous article as these are the backbone of Angular2. The only difference here is the service, HelloService. However, if you notice, the service is itself a ES6 Class similar to our application component, DI. Just like @Component annotation is there to tell Angular2 to treat a ES6 class as a component, the @Injectable annotation annotated the ES6 Class as an Angular2 Service that is injected elsewhere.

In the above example, we’ve injected the service via providers options in the @NgModule. This way the instance of the service will be available for the entire component only and its child components, if any. However, services in Angular2 are not singleton by nature unlike Angular1 which means if the same service is injected as a provider in a child component, a new instance of the service will be created. This is a confusing thing for beginners so watch out.

The public Hello: HelloService parameter in the constructor is equivalent to Hello: HelloService = new HelloService();. It means Hello is an instance of HelloService and of a type HelloService (optional). One benefit of annotations/decorators in Angular2 in my opinion is that there is no confusion over Factory vs Service vs Provider, instead it’s just a ES6 class.

Slight changes compared to the previous example is that we need to give more configurations in SystemJS for typescript compilers to emit decorator MetaData so that generated ES5 code will work fine in a browser.

{
  "compilerOptions": {
    "target": "ES5",
    "module": "commonjs",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false
  }
}

Remember experimentalDecorators flag enables experimental support for ES7 decorators in TypeScript and emitDecoratorMetadata flag emits design-type metadata for decorated declaration in ES5 output, especially, for public Hello: HelloService code in the constructor as we’d seen before. Using the alternative mentioned above will not need these flags though.

Now let us update HTML markup.

<html>
<head>
  <title>Angular2: DI</title>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <!-- 1. Load libraries -->
  <script src="../node_modules/core-js/client/shim.min.js"></script>
  <script src="../node_modules/zone.js/dist/zone.js"></script>
  <script src="../node_modules/reflect-metadata/Reflect.js"></script>
  <script src="../node_modules/systemjs/dist/system.src.js"></script>

  <!-- 2. Configure SystemJS -->
  <script src="../systemjs.config.js"></script>
  <script>
    System.import('ch01/di').catch(function(err){ console.error(err); });
  </script>
</head>
<body>
  <!-- 3. Display the application -->
  <ng-app>Loading...</ng-app>
</body>
</html>

Wrap up

That’s it guys..! Wolksoftware‘s blog has covered a great intro to reflection in Typescript, if interested. In the next post, we’ll explore two-way databinding in Angular2, but meanwhile Checkout Dependency Injection in action.

Angular2: The First Time


Angular 2.0 is lot like Angular1 but still different in its own terms and you’ll see why as we go along. Purpose of this article is to migrate one of the simplest Angular1 examples to Angular2 and understand benefits as well as pain-points. For the record, Angular2 aimed to build web applications in three different languages or flavours i.e. JavaScript (ES5/ES6), Typescript(ES6+), and Dart. If you interested in other two then the 5-minute-session will give you a head-start to understand how it could be done. However, I’m going to use Typescript over JavaScript here because in my opinion it feels more natural. This article is for the ones who worked with Angular1 before.

Angular1

Let’s take a simple example (HTML and JS) from my free e-book on Angular1 Directives that explores how data binding works in Angular1. Let us quickly take a look at our good old Angular1 HTML template and then we’ll move to new shiny Angular2 version of it. But for now, notice we’ve used ngBind directive over double-curly notation for data-binding, obviously to avoid FOUC as we all know. Also checkout ngApp directive which was a recommended way to bootstrap an application automatically in Angular1 without using angular.bootstrap method.

<html ng-app="App">
<head>
  <title>HTML/DOM Template in AngularJS</title>
  <script type="text/javascript" src="../bower_components/angular/angular.js"></script>
  <script type="text/javascript" src="../js/ch01/angular-template.js"></script>
</head>
<body>
  <span>Hello, <span ng-bind="name"></span></span>
</body>
</html>

Here is the JavaScript code for the above example which simply binds a value of name property on the $rootScope.

var App = angular.module('App', []);
App.run(function($rootScope) {
  $rootScope.name = 'AngularJS';
});

Now that we’ve our demo up and running, its time to migrate it to Angular2.

Angular2

Let us first update the JS code and walk-through the changes. Give it a very long, hard stare to get familiar with the following snippet, I’ll wait.

import { NgModule, Component } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

@Component({
  selector: 'ng-app',
  template: '<span>Hello, <span [textContent]="name"></span></span>'
})
class MyAppComponent {
  name: string = 'Angular2';
}

@NgModule({
  declarations: [MyAppComponent],
  imports:      [BrowserModule],
  bootstrap:    [MyAppComponent]
})
export default class MyAppModule {}

platformBrowserDynamic().bootstrapModule(MyAppModule);

Your first reaction would be, “Alright, that looks familiar..!”. Well it is except few things, let us go over one by one. But before that we must know that Angular2 moved from a concept of directives to components to leverage web-components specs so that developers can use Polymer components with Angular2 templates. Basic idea is to break down monolithic application into small pieces i.e. components and plug them together at the end under main component like we have here. Each component should have one or more Classes or Functions to store data (name in this case) and necessary methods (not defined in the example above). Please note we no longer use $scope in Angular2 as this is somewhat like CtrlAs syntax from Angular1. When Angular2 instantiates MyApp class, all properties or methods defined will be accessible via keyword this.

Update: As per RC5 release, angular2 introduced a concept of NgModule metadata which plays an important role in the compilation process, especially offline compilation. Because of NgModule, Angular2 will able to lazy load components on demand by resolving component dependencies efficiently. So every component should expose a NgModule for other components to import and reuse. Ideally, NgModule should be extracted into it’s own file importing various components, services, pipes, etc. but for the sake of readability, we’ll have it in the same file along with the component.

export statement

Angular2 has adopted modularity at its core unlike Angular1 wherein you could only define modules without any built-in support for lazy loading. Using ES6 export module syntax, you can export functions, objects, or primitives that other classes can use in Angular2. Having one export class per module recommended though. We’ve defined a property, name with a type string which is optional in TypeScript.

Import Statement

With the same export class syntax, Angular2 has organized its code base so that developers can import what they need in a module. In this example, we are only importing Component and NgModule annotations from angular2/core library and platformBrowserDynamic method from angular/platform-browser-dynamic modules. Note that the extension is optional in the definition.

Using platformBrowserDynamic().bootstrapModule method from angular2 browser module (similar to angular.bootstrap in Angular1), we can bootstrap the NgModule named MyAppModule. Angular2 is a lot different from Angular1 on the architectural level. Angular1 only targeted Desktop and Mobile web browsers, but Angular2 is platform agnostic, that means it can be used to write Native mobile apps using NativeScript or Cordova, run angular2 application inside web workers, and to enable server-side rendering with NodeJS or so. For now, we’ll just run it in a web browser by pulling down browser specific bootstrap method as above.

Annotation

The strange-looking syntax above the class called as a Class Decorator that annotates and modifies classes and properties at design time. Wolksoftware’s engineering blog has great articles on decorators and metadata in Typescript. In a nutshell, Angular2 uses decorators/annotations to make dependency injection possible. To simplify it, let us take a small requirement.

Imagine you want to log a function name and passed arguments to browser console every time a method invoked without modifying the function body. In the following example, @debug is a method decorator that attached a special behavior to the method body. overtime a method called, the decorator will find a method name being called and it’s parameter that we can log. Here is a working demo if interested.

export class AnnotationExample {
  @debug
  life(n: number) {
    return n;
  }
}

function debug(target: Function, fnName: string, fn: any) {
  return {
    value: function (argument: number) {
      document.getElementsByTagName('body')[0].textContent = `function "${fnName}" was called with argument "${argument}"`;
    }
  };
}

var whatIs = new AnnotationExample();
whatIs.life(42);

On the same note, @component annotation/decorator tells Angular2 that the defined class, MyApp is an Angular2 Component not just a ES6 class. And once it’s defined as the component, Angular2 needs to know how the component supposed to be consumed in HTML or which template to render once it’s registered. That’s why we need to pass the meta data as above such as selector, template, etc.

Notice selector name need not be the same as the class name unlike Angular1. There is no restrict option anymore, instead use a tag name (ng-app) or a property name (with square brackets [ng-app]) or a class name (.ng-app) directly as a selector (I think a comment selector is dropped..!). Also note that we have used a double curly notation for data binding here as there is no ngBind directive available, but you can use property binding (which we’ll explore in future posts) to get the same feeling with <span>Hello, <span [textContent]="name"></span></span>.

Now let us update HTML markup.

<html>
<head>
  <title>HTML/DOM Template in Angular2</title>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <!-- 1. Load libraries -->
  <script src="../node_modules/core-js/client/shim.min.js"></script>
  <script src="../node_modules/zone.js/dist/zone.js"></script>
  <script src="../node_modules/reflect-metadata/Reflect.js"></script>
  <script src="../node_modules/systemjs/dist/system.src.js"></script>

  <!-- 2. Configure SystemJS -->
  <script src="../systemjs.config.js"></script>
  <script>
    System.import('ch01/angular-template').catch(function(err){ console.error(err); });
  </script>
</head>
<body>
  <!-- 3. Display the application -->
  <ng-app>Loading...</ng-app>
</body>
</html>

If you remember, we’d included just angular.js in Angular1 template before, however, Angular2 relies on couple of other JavaScript libraries that you need to inject along with it. But things may change eventually, as it’s just a RC release (at the time of writing this article, and who knows we have to just include one file as before).

Refer SystemJS Wiki for more details to suite your needs. And as you guessed already, we have created a custom element in the body at the end to kick it off.

Wrap up

Peek at a demo..!. That’s it guys..! This is the exact flow you’ll always be using to write new components in Angular2. I liked the progress with Angular2 and Typescript, I would recommend to use Visual Studio Code Editor over SublimeText to feel at home. Be hopeful that many of the things we explored would be simplified by the time it reaches 1.0 (stable), I mean 2.0 πŸ˜‰

Protractor: The Secret Service


This post is not about how to install and use Protractor. I believe setting up Protractor is a lot easy, so heading over to the documentation is an ideal choice to make. For those who have not heard of Protractor yet, it is nothing but an end-to-end test framework for AngularJS applications. However, it works seamlessly for non-angular applications as well, obviously, with a small tweak which is what this post is all about.

In a nutshell, Protractor runs tests against your application running in a real browser, interacting with it as a user would. That means you have to give a set of instructions for each test you write. But before that, let us create a small demo in jQuery (no AngularJS). Below demo is fairly simple but useful to put my point across about robustness of writing tests in Protractor. In this demo, we are having a dummy Google Sign In button loaded via a fake REST call to Google Developers APIs.

<!DOCTYPE html>
<html>
<head>
	<title>Protractor: The Secret Service</title>
	<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
	<script>
	$(window).load(function() {
		// Simulating a REST call with Google APIs
		window.setTimeout(function() {
			$('#signin-placeholder').replaceWith(
				'<button id="signin">Google Sign In</button>'
			);

			$('#signin').click(function() {
				$(this).text('Sign Out');
			});
		}, 2000);
	});
	</script>
</head>
<body>
	<div id="signin-placeholder"></div>
</body>
</html>

Sleep

Now that we understood how our application works, it’s time to write E2E tests for it. Following test block might look sound and easy to grasp to you, but there are couple of hidden tricks have been used in order to pass it.

describe('Non EC Tests', function() {
	beforeEach(function() {
		browser.ignoreSynchronization = true;
		browser.get('demo.html');
	});

	it('Should', function() {
		browser.sleep(2 * 1000);
		element(by.id('signin')).click();
		expect(element(by.id('signin')).getText()).toBe('Sign Out');
	});
});

First line in the beforeEach block i.e. browser.ignoreSynchronization is to tell Protractor that, Hey, this is not an Angular application, so do not wait for Angular to load. Start running tests as soon as the page loads in a browser. This is the one and only trick to consider while using Protractor for non-angular applications which means if in case a webdriver control flow hangs while running tests, that’s the thing to look for in the Spec. Moving on to the it block which is our actual test. In the beginning, we make sure to wait for 2 seconds as per our business logic before we click the login button. Later we confirm the button text is changed to Sign Out.

The important thing to note here is that the browser.sleep method is a last resort most people use to make tests pass to prevent random failures, however, in our case, it is tightly coupled with the business logic. If we increase/decrease the timeout in the fake REST call, we’ll have to adjust the same to fix the broken test. In addition to it, the real REST call may or may not complete within the expected timeout making your test unstable. Let’s fix that…

Wait

Selenium webdriver exports a method called browser.driver.wait that schedules a command to wait for a condition to hold true. This means wait will repeatedly evaluate the condition until it returns a truthy value. You can pass a condition or a custom function that returns a promise to it. So we will simply replace the browser.sleep statement with,

browser.wait(element(by.id('signin')).isDisplayed, 2 * 1000);

In here browser will wait until isDisplayed method returns a truthy value. If it did not, it will time out after 2 seconds. Note in protractor version 2.0.0, due to changes in WebDriverJS, wait without a timeout will now default to waiting for 0 ms – which off-course forbids our business logic. So we chose to provide ideal explicit timeout. To your surprise the above statement will throw, Failed: No element found using locator: By.id("signin") error because it’s not available in the DOM yet. We could have used browser.waitForAngular method for Angular to render the button if we were using it in the demo. Protractor deals with such scenarios nicely, especially in Angular applications wherein it forces the webdriver to wait until Angular has finished rendering and has no outstanding $http or $timeout calls before continuing.

ExpectedConditions

No worries..! Selenium offers a different mechanism to handle the same for Protractor called as ExpectedConditions a.k.a. EC. It’s similar to protractor isDisplayed API that we saw earlier but especially for non-angular applications. Again the webdriver waits until the expected condition returns a truthy value. Moreover, you can mix it with multiple and, or, and not operators. So to fix the error, we’ll use,

browser.wait(protractor.ExpectedConditions.visibilityOf(
  element(by.id('signin'))
));

This will schedule a command for the webdriver to wait and repeatedly evaluate the condition to check if the element is available/visible in the DOM. There are various functions EC supports that you should take a look at http://www.protractortest.org/#/api?view=ExpectedConditions.

Wrap up

So that’s it. In a real-world project, I happened to encountered similar issues on staging environment where pages load slighly slow than local webserver and some of my tests started failing randomly because browser.sleep hack for HTTP or AJAX calls did not pan out :-). EC statements have helped me a lot while writing robust Protractor tests for non-angular apps and made tests more stable too, mostly, on Firefox and Safari.

Thanks for reading and keep Rocking \m/.

AngularJS Directives: A forerunner of Web Components


Update: I’ve published a free book on Git Books.

This chapter covers

  • The core features and benefits of AngularJS
  • What problems AngularJS Directives solve and why they are worth learning
  • How AngularJS Directives mimic Web Components – the Future Standard

If you are reading this book then you might be aware of AngularJS and quite curious to know about what it can offer. In case you are a JavaScript developer or jQuery addict and would like to port some of your jQuery plugins to AngularJS, then this book is for you. Pat yourself on the back for making the right choice and choosing to invest your precious time into the precious to make yourself productive to write your next ambitious application or component.

In this chapter, I’ll give you an overview of features and benefits of AngularJS as a whole, as well as describe how AngularJS Directives are helping to shape the future of web applications. We’ll start off with understanding the magic behind AngularJS popularity and then get to know directives straightaway.

3Ds of AngularJS – data binding, dependency injection, and directives

AngularJS is built around the belief that declarative programming should be used for building user interfaces and wiring software components. By declarative means that it adapts and extends traditional HTML to better serve dynamic content through two way data binding that allows for the automatic synchronization of data and User Interfaces. With this, AngularJS reduces imperative DOM manipulation (like we do with jQuery) and improves testability by facilitating separation of concerns.

HTML is great for declaring static documents, but it falters when we try to use it for declaring dynamic views in web applications and we often end up with spaghetti code – a mixture of HTML and JavaScript, which is inexpressive, unreadable, and hard to extend further. Other frameworks work around the HTML’s shortcomings by abstracting away HTML, CSS, and JavaScript in terms of UI Widgets or by providing an imperative way for manipulating the DOM. But none of these solutions address the problem developers face while developing dynamic applications. Instead, AngularJS lets you write applications in a declarative manner that not only speeds up the development process but also makes it easy to test, extend, and maintain as applications grow large. AngularJS came into existence to make the web better and browsers smarter, but it did so before it would be supported natively in terms of Web Components. In fact, it truly allows us to write composable and reusable components declaratively to facilitate code abstraction.

Going forward we’ll take a look at what makes AngularJS so special.

Making HTML dynamic with Data Binding

Who does not like to give commands and have followers to follow them? Data Binding is based on the same notion wherein data models are like commands and are being constantly followed by Views to be updated automatically. Data Binding is a very old concept (new to JS) notably used in Adobe Flex. It is one of the core features of AngularJS that makes the overall framework magical and helps us reduce lines of code (LOC) by doing the heavy lifting itself so we do not have to do DOM manipulation manually and repeatedly.

To understand it better, let us look at a simple but real-world example. Let’s say we have a notification panel in our application to show messages that needs to be updated every time a new message arrives. In JavaScript, we would probably do as follows.

<html>
<head>
  <title>Updating Notification Panel in Pure JS</title>
</head>
<body>
  <div id='notification'>No Message found.</div>

  <script type="text/javascript">
    document.getElementById('notification').innerHTML = 'Learning Angular Data Binding';
  </script>
</body>
</html>

There could be many places in your application from where you could update the notifier and have to use a long-lasting and painful DOM APIs depending on the complexity of the DOM you are dealing with. You may have to write lot of repetitive code for every HTML element that has to be updated dynamically from several places which is cumbersome and unmanageable as your application grows.

What if there were a simpler and better way to handle this? Well, in AngularJS, any type of data (primitives and objects) is a model and once bound to the DOM will update it automatically whenever the associated model changes. So the same thing can be accomplished using data binding in AngularJS as shown in the following listing.

<html ng-app="App">
<head>
  <title>Updating Notification Panel in AngularJS</title>
  <script src="http://code.angularjs.org/snapshot/angular.js"></script>
</head>
<body>
  <div ng-bind="notification || 'No Message fund.'"></div>

  <script type="text/javascript">
    angular.module('App', []).run(function($rootScope) {
      $rootScope.notification = 'Learned Angular Data Binding, Today';
    });
  </script>
</body>
</html>

With this approach, you are assured that the notification panel will automatically update whenever the notification model changes. Just imagine how easy is it to enable two-way data binding with ngBind directive.

You might be curious to ask, Will it update the model as well if I dynamically change the content of the <div>? Nope. That is because it’s a one-way data binding we’ve set up in this case. The two-way data binding can be achieved with Form Controls such as Input, Textarea, Select, Checkbox, Radio, and so on.

<html ng-app="App">
<head>
  <title>Two way Data Binding with Form Controls</title>
  <script src="http://code.angularjs.org/snapshot/angular.js"></script>
</head>
<body>
  <input type='checkbox' ng-model='choose' />
  <div ng-bind="choose"></div>

  <button ng-click="choose=!choose">Toggle Checkbox</button>

  <script type="text/javascript">
    angular.module('App', []);
  </script>
</body>
</html>

We can update <div>‘s content by either ticking the checkbox or directly updating the model in JavaScript as seen before. So directives let us make HTML dynamic by applying directives so that HTML can interact the way we want it to be.

I’m pretty sure you must be grinning by now considering the possibilities of what you can do with this new learning.

Managing dependencies with Dependency Injection

Dependency Injection (DI) is a software design pattern that deals with managing dependencies. This allows the removal of hard-coded dependencies and makes it possible to change them, whether at run-time or compile-time. A dependency can be resolved either by creating (using the new operator) or passing a reference of the already created object where it’s needed. The first approach is not optimal because we then need to hard-code the dependency, thereby making it difficult to modify later or even test. The second option is viable, as we do not have to instantiate the dependency ourselves; we can just hand it over. This makes testing easy as we can mock the dependency at will without knowing how it was created. To get more clarity on the subject, let us look at a trivial example given as follows.

In JavaScript, we often define a Class and create an instance of it to access its properties or methods. In this example, sayHi() class is dependent on hello() class. But, the way we’ve resolved the dependency by creating an instance of hello() class manually is not ideal. If, in case, the constructor definition of the hello() class changes in future, it will affect our class, sayHi as well.

function hello(who) { this.name = 'Hello ' + who; }
function sayHi(obj) { return obj.name; }

var objHello = new hello('AngularJS');
console.log(sayHi(objHello));

What if we could instantiate all the dependencies in one place and just pass the references wherever needed? This will loosely couple all the dependencies, and any modifications later will not affect components that were dependent on it. That’s how AngularJS manages dependencies using the Dependency Injection (DI) system built-in:

var App = angular.module('DI', []);
App.service('Hello', function() {
  var self = this;
  self.greet = function(who) { 
    self.name = 'Hello ' + who;
  }
});

App.controller('SayHi', function(Hello) {
  Hello.greet('AngularJS');
  console.log(Hello.name);
});

In this example, we have a class named Hello defined via service method in AngularJS. Then we have injected the same as a dependency in the controller, SayHi, which calls greet method with a parameter – whom you wish to greet. Just pay attention to how the dependency has been resolved without creating an instance of Hello implicitly. Off-course D.I. internally instantiates the class and stores its instance into the same object passed before.

This approach makes it really easy to mock all dependencies during testing so we can test SayHi in a complete isolation by mocking the service Hello used with.

FYR, Testing code would look something like:

describe('Resolve Dependencies', function() {
  var SayHi, Hello;
  
  beforeEach(module('DI')); 
  beforeEach(inject(function($controller) {
    Hello = {
      greet: function(who) {
        Hello.name = 'Hello ' + who;
      }
    };

    SayHi = $controller('SayHi', {Hello: Hello});
  }));
});

That’s it! AngularJS will automatically resolve dependencies while testing and use the mocked service instead of the original one.

Scaffolding reusable markups as HTML Template

The purpose of JavaScript Templating is to generate HTML that makes sense based on structured data. Such templating libraries take JSON data and compile it into a function which can then be used to generate the final HTML by passing in values for placeholders. There are two types of templating libraries:

  1. String-based
  2. DOM-based

In string-based templating, we wrap an HTML into a pair of <script> tags, compile, and interpolate it with JSON data to get the final HTML string – which can be injected in the page later. Underscore.js, Handlebars.js, Mustache.js are some of the well known examples of this category. Here is how templating works in Underscore.js. It introduces a special method _.template() to feed in the template that generates a compiled function. The compiled function then takes JSON or JS objects to interpolate the template.

As per the following figure, the moment we update the model, each time the whole template will be recompiled and re-rendered in the browser.

How Templating works in Underscore.js
How Templating works in Underscore.js

The <%= name%> expression is a syntax in Underscore.js to create a placeholder for name. The trade-off of this approach is that as the template becomes larger, the amount of stuff that needs to be re-rendered grows, which is slow and wasteful.

In contrast, AngularJS uses HTML(DOM) as a template where only specific parts of the template updates when the model changes. The benefit of this approach of updating only the fragments of the HTML document is that it does not re-render the whole template every time but just updates those parts of the template that were associated with the models. What this means is that it introduces various directives such as ngBind, ngBindHtml, and so on to achieve this. It supports {{ }} as a templating syntax as an alternative to <%= name%> in underscore but you could use ngBind built-in directive as well to achieve the same as shown in the following listing. Create angular-template.html in ch01/ directory as:

<html ng-app="App">
<head>
  <title>HTML/DOM Template in AngularJS</title>
  <script src="https://code.angularjs.org/snapshot/angular.min.js"></script>
  <script type="text/javascript" src="../js/ch01/angular-template.js"></script>
</head>
<body>
  <span>Hello, <span ng-bind='name'></span></span>
</body>
</html>

Then add following snippet in js/ch01/angular-template.js so:

var App = angular.module('App', []);

App.run(function($rootScope) {
  $rootScope.name = 'AngularJS';
});

When AngularJS bootstraps, it compiles the HTML and feeds in the actual data replacing the placeholder, ng-bind='name'. All this is done by AngularJS in the background and hence it looks very natural and easy to write or manage.

More specifically, in this example, only span tag will be updated if name updates to something else later, unlike string-based templates, where the entire template string has to be interpreted in order to replace just the name expression. Let’s see how AngularJS does it:

How Templating works in AngularJS
How Templating works in AngularJS

As you can notice that all the pieces such as a template, data model, and view remain the same as in string based templates but the very difference lies in the compilation of the template which only happens once. Furthermore, data binding takes care of updating relevant parts of the view (instead of entire view) upon model mutation.

Deep Linking AngularJS applications to maintain browser history

Back in the old days, every hyperlink used to refresh the page in order to load it. AJAX (Asynchronous JavaScript and XML) opened the door to load content asynchronously without refreshing a page at all. Developers found a profound way to write applications without a single refresh and hence coined a term, Single Page Applications. With AJAX, web applications can send data to, and retrieve data from, a server asynchronously. Google made a wide deployment of standards-compliant, cross browser AJAX with Gmail and Google Maps. But while doing so, many of the applications were breaking the browser’s back button – there was no longer a way to go back to the previous hyperlink visited.

AngularJS does not break the back button, thanks to Routing. It comes with a routing module named ngRoute, which enables you to programmatically generate URLs based on route definition. As given in the following example, we’ve injected ngRoute as a dependency (thanks to DI) that provides access to the $routeProvider service to define our routes. Let us look at the following route example as:

angular.module('ngRouteExample', ['ngRoute'])
.config($routeProvider) {
  $routeProvider.when('/Book/:bookId', {
    templateUrl: 'book.html',
    controller: BookCtrl
  }
});
<div ng-view>Template loads here</div>

In this example, I’ve set up a simple route to load book details by its Id. When user opens http://myapp.com/Book/2 in the browser, AngularJS’s internals notify the $routeProvider service to match the URL format with each of the route definitions and attempts to match the URL format (/Book/:bookId) with the URL value (/Book/2) in the defined route configuration list (where :bookId acts like a parameter). As expected, it will match with the preceding route definition and load book.html partial thereafter into the div element.

To make it work, AngularJS provides a special directive named ngView which renders a template of the current route into the main layout. Whenever current route changes, the view updates as well according to the route definition. It does not look like a big deal to set up routes, but it is an extremely important and powerful module in AngularJS arsenal, especially in the era of Single Page Applications.

Testing is !important

AngularJS is written with testability in mind, and there is no reason why one should not write test cases for any snippet. In fact, there is nothing you can write in AngularJS that cannot be testable. If one cannot, then he is doing it wrong. I would recommend every AngularJS developer to write testable code. The same approach we’re going to follow throughout the book.

You as a developer might have gone through a situation (many times) wherein an application stops working or behaves abnormally after fixing a bug or implementing a feature if you’ve not set up an automated testing environment. And it’s very difficult and time consuming to go through all the test cases manually to check if anything is broken every time you do any updates. To solve such problems, the AngularJS team has built many features, libraries, and tools to make testing a First Class citizen. There are two ways to do testing in AngularJS: unit testing and end to end testing.

UNIT TESTING

Unit Testing, as the name implies, is all about testing individual units of code i.e. functions. To make unit testing fundamentally more accurate, we have to follow Unix Philosophy – write programs/functions that do one thing and do it well. There are many unit testing frameworks, such as Jasmine, Mocha, Chai, Qunit, and so on, but Jasmine has been used at its core so we’re going to use the same for all our examples in this book.

If we were to write a unit test for the example we saw before ch01/angular-template.html. We would probably do as follows by creating tests/specs/ch01/angular-template-unit.js so:

describe('Test AngularJS Template', function() {
    beforeEach(module('App'));  
    var element, scope;

    it('Should update an element', inject(function($rootScope, $compile){
        $rootScope.name = 'AngularJS';
        element = angular.element(
         '<span>Hello, <span ng-bind="name"></span></span>'
     );
        element = $compile(element)($rootScope);
        $rootScope.$digest();

        expect(element.text()).toBe('Hello, AngularJS');
    }));
});

In this simple test snippet, we’ve set up a Jasmine framework to run the test. In Jasmine, describe() block allows you to group related tests cases and it() block lets you write the actual test to perform. In this case, we’ve injected two dependencies, namely, $rootScope and $compile. The $rootScope is single root $scope that every AngularJS application has. Later we create a DOM in memory using angular.element() – an alias for the jQuery ($) object and compiled it by passing in the $rootScope to the $compile service – that replaces placeholders with actual values on the scope. Finally, we make sure that the element contains the valid text with expect() – an expectation in Jasmine is an assertion which implements comparison between the actual value and the expected value.

Unit Test Report for AngularJS Template example in Jasmine
Unit Test Report for AngularJS Template example in Jasmine

At the end, Jasmine will show you above display if the test succeeds.

END TO END TESTING

No matter how good programmer you are, you cannot presume that every piece of code you write will work as expected on various browsers; hence, functional testing is extremely important, and there is a need for End to End test frameworks. Protractor is an end to end test framework specifically for AngularJS applications built on top of (a wrapper for) WebDriverJS – Selenium Web Driver which is a standard web applications testing tool used everywhere. The installation of Jasmine with Karma Test Runner and Protractor with Selenium Driver is covered in detail in Chapter 3. Luckily Protractor supports Jasmine like syntax to write test cases so that you can grasp it in no time. Let us quickly check out how to write test cases in Protractor, so create tests/specs/ch01/angular-template-e2e.js as:

describe('Test AngularJS Template', function() {
  var str;

  it('should greet AngularJS', function() {
    browser.get('ch01/angular-template.html');
    str = element(by.binding('name')).getText();
    expect(str).toEqual('AngularJS');
  });
});

In the describe() block, we are creating an instance of protractor and loading a page to perform tests on. As soon as we run protractor on a command line, browser.get() will fetch the specified html page in real browsers and perform a lookup for the binding, {{name}} using by.binding() syntax. Finally we’re just matching the actual value with the expected one. If everything goes well then this is what you’ll see in the command line.

E2E Test Report for AngularJS Template example in Protractor
E2E Test Report for AngularJS Template example in Protractor

So AngularJS framework is extremely conscious about testing every bit of AngularJS applications, even directives are no exception!

Meet AngularJS Directives

By now we have covered AngularJS in a nuthshell and you probably excited to get to know AngularJS directives. So, here we go. HTML is all about elements, but as the web grew bigger, developers started building complex applications so the existing elements fell short to fill the gap and we chose to rely on markups with lots of JavaScript. The basic idea is that the current set of elements we have in HTML always perform the same role and have the same set of properties/options applied to it but the web today has to do lot more work and HTML can’t keep up with the rate of change.

Browsers have engrossed the specification required to analyze the behavior of HTML elements so they understand the language and figure out the layout when a web page loads. But they are not able to interpret the meaning of custom HTML element which is not part of the specification they know. In such condition, the browsers simply consider it as a text content ignoring the element altogether.

AngularJS Directives API teaches the browsers a new trick and helps them to treat custom elements as native ones. Also, it gives developers flexibility and low-level access to create custom elements based on their function. Hence directives are the integral part of the AngularJS framework and the only thing that makes AngularJS stand out from the crowded list of JavaScript frameworks these days. Let us see what are directives made up of.

What are directives

AngularJS Directive is nothing but the way to expand HTML vocabulary. Having said that you can extend existing HTML element or create a new one by encapsulating custom behaviors atop. That means, we can write custom elements, attributes, and so on in AngularJS that browsers can understand using AngularJS Directives API. Here is a non-intuitive example of Accordion widget in Twitter Bootstrap as:

<html>
<head>
  <title>Accordion in Twitter Bootstrap</title>
  <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
  <script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
  <script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
</head>
<body>
  <div class="panel-group">
    <div class="panel panel-default">
      <div class="panel-heading">
        <h4 class="panel-title">
          <a data-toggle="collapse" href="#accordion1">
            Accordion Header #1
          </a>
        </h4>
      </div>
      <div id="accordion1" class="panel-collapse collapse in">
        <div class="panel-body">Accordion Body #1</div>
      </div>
    </div>
    <div class="panel panel-default">
      <div class="panel-heading">
        <h4 class="panel-title">
          <a data-toggle="collapse" href="#accordion2">
            Accordion Header #2
          </a>
        </h4>
      </div>
      <div id="accordion2" class="panel-collapse collapse">
        <div class="panel-body">Accordion Body #2</div>
      </div>
    </div>
  </div>
</body>
</html>

However, it does fulfill the requirement of having a fancy looking accordion widget in the browser but at the expense of imperative markups that you dare to fiddle. The end-users who will end up using this UI widget no longer need to go through the pain of understanding nitty-gritty things in their way just to use the component. What they really want is the minimal, comprehensible, and declarative piece of code that makes sense to them. Up until, it was not possible to have that level of encapsulation in order to hide the complexity behind the curtain and only show things that matter to the end-users. Here is the same example converted into a declarative style using AngularJS directives API for you to get a sense of what AngularJS directives can do:

<html ng-app="App">
<head>
  <title>Accordion in AngularUI Bootstrap</title>
  <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
  <script src="https://code.angularjs.org/snapshot/angular.js"></script>
  <script src="http://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.10.0/ui-bootstrap-tpls.js"></script>
  <script type="text/javascript">
    angular.module('App', ['ui.bootstrap']);
  </script>
</head>
<body>
  <accordion>
    <accordion-group heading="Accordion Header #1">
      Accordion Body #1
    </accordion-group>
    <accordion-group heading="Accordion Header #2">
      Accordion Body #2
    </accordion-group>
  </accordion>
</body>
</html>

Now the thing is that you will find this piece of markups much more comprehensible than the one that we saw earlier. Note that, even it looks human readable by now, it still generates the same blob of markup behind the scene but hides it upfront to make it declarative and fun to interact with.

Even though this book is all about directives and we are going to explore all the configurations required to define directives in subsequent chapters, following is the blueprint for your reference.

angularmodule('MyModule', []).directive('directiveName', function () {
  return {
    restrict: 'A',
    template: '<div></div>',
    templateUrl: 'directive.html',
    replace: false,
    priority: 0,
    terminal: false,
    scope: false,
    compile: function (tElement, tAttrs, transclude) {
      return {
        pre: function preLink(scope, iElement, iAttrs, controller) { },
        post: function postLink(scope, iElement, iAttrs, controller) { }
      }
    },
    link: {
      pre: function preLink(scope, iElement, iAttrs, controller) { },
      post: function postLink(scope, iElement, iAttrs, controller) { }
    }
    transclude: false,
    controller: function($scope, $element, $attrs) { },
    require: 'otherDirectiveName'
  };
});

These are the parameters the directives API supports to compose a directive, so here is a quick tour:

Restrict: Restricts the directive to a specific DOM declaration style. Can be an element or attribute by default.

Template: Stuffs the element binded to the directive with an extra content to be injected dynamically.

TemplateUrl: Same as templateUrl but the template will be loaded asynchronously via AJAX or XHR.

Replace: Replaces the element with the template added by template or templateUrl option.

Priority: Configures the order in which directives are applied or compiled.

Terminal: Freezes the further compilation of directives on the element, if set to true.

Scope: Different types of scope strategies depending on the requirement.

Compile: Deals with transforming the template or element.

Link: Responsible for registering DOM events and bindings variables on the scope to be used within the template.

Transclude: Brings the content of the element into the template. Works even if replace set to true.

Controller: Allows to share scoped methods or properties with other directives (siblings or child directives).

Require: Injects the controller of a sibling or parent directive in order to use shared scoped method or properties.

You will notice that the blueprint is quite huge and complex but trust me its worth learning. So the takeaway is that the directive is:

  • The place for Imperative DOM Manipulation
  • The home for binding DOM events and unbinding them later
  • The technique to facilitate code reuse with semantic and composable widgets
  • The ability to write or use code declaratively
  • And ultimately the way to extend HTML vocabulary

Now let us see how directives actually work behind the scene in the following section.

How directives work

In short, AngularJS when bootstrapped, looks for all the directives built-in as well as custom ones, compiles them using built-in compiler, and links with the associated scope by registering listeners or setting up $watches resulted in 2 way data bindings between the scope and the element.

If this is overwhelming for you, here is the smallest directive that you can possibly ever write. However, it does not do anything but just there to explain how directives get registered in AngularJS. We have defined a custom directive named noop that can be used as an attribute/element as shown:

<html ng-app="App">
<head>
  <title>Basic Directive: noop</title>
  <script src="../bower_components/angular/angular.js"></script>
  <script type="text/javascript">
    var App = angular.module('App', []);

    App.directive('noop', function() { return {}; });	#B
  </script>
</head>
<body>
  <div noop></div>
</body>
</html>

Few things to note here is that:

  • The ngApp directive is an important built-in directive you’ll always need per application to bootstrap the same.
  • We then register our directive named noop that means no operation as it does not alter or modify the associated element or node. However, this will still be registered by AngularJS because of the default properties set internally such as restrict (as an attribute/element by default) in the DOM and priority (0 by default) to set the order of execution. This further added into an injector – built-in service that can be used to retrieve object instances to check if it is a directive or an existing HTML node during DOM compilation that we’ll see next.
  • Finally we use it as a custom attribute/element in the DOM and you’ll see just a div element in the DevTool. However, you must be nagged by a question that how does AngularJS do it?

That’s quite simple than you think. All it does is the compilation of the HTML tree to find directives to activate them. On a high level, it is quite similar to how browser parses HTML and displays the output. Take an example of an anchor element (<a>) that turns a normal text into an underlined one with blue font color by default. As discussed before that the browser has a specification of the anchor element, it just performs the required operations to attach those behaviors. Similarly there is a flow of how AngularJS brings directives to life:

  1. First it finds where to start the compilation process and that’s why AngularJS needed a unique marker to begin with. The ngApp directive serves that purpose. The element or node (including all of its child nodes) on which it is applied will be owned by AngularJS for further operations such as directives registration, data bindings, and so on. Thus AngularJS does not bootstrap without it. Many beginning AngularJS developers often forget to add the ngApp directive until they realize why their directive did not work.
  2. Once it knows the root node, it traverses the DOM to find sub nodes (elements, attributes, classes, and comments), and maps each with the injector service to check its definition exists or not. This process helps AngularJS to collect all the directives per node and to return their compile functions.
  3. The Compile function per directive is executed in order to apply behaviors on the respective node. Prior to this step, directives do not exist at all for the browser. This step creates a new or shared scope per directive (depending on its definition) needed to create watchers and set up data bindings in terms of Link functions.
  4. Finally the link functions are executed in a reverse order than that of the compile functions to register DOM events or update bindings used on elements or within their templates. There is a reason for the reverse ordering which we’ll cover in Chapter 4. By this step, the directives are fully activated, probably manipulated the DOM, updated the bindings, attached the DOM events, and so on.

By now, we know that AngularJS activates directives but what does it mean? Let us slightly update the noop directive to see it in action as:

App.directive('noop', function() {
  var count = 1;
  
  return {
    compile: function(cElement) {
      cElement.html('I am noop {{counter}}');

      return function link(scope, element) {
        scope.counter = count;
        count++;
      }
    }
  };
});

We have added the compile function which is basically used to manipulate the associated element and update its content. Note that the double curly notations are very common data binding syntax used in AngularJS, you can also use built-in directives replacing the same such as ngBind, ngBindTemplate, and ngBindHtml.

As learned before, the compile function generates a link function that gives access to scope object and you are good to go with binding few scope variables to enable two way data binding in this phase. We have set the counter variable that updates the binding {{counter}} placed earlier in the DOM. You should see “I am noop 1” in the browser now.

You probably think that why there is a need for compile and link functions? Why not combine them? The only reason for the existence of the compile function is performance. To find out, let us update the noop directive in HTML as:

<div noop ng-repeat="item in [1, 2, 3, 4, 5]"></div>

Here we basically repeat the same div element five times and each time the noop directive will be linked to a new instance of the DOM. And you will see “I am noop 1”, “I am noop 2”, and so on as the counter increments. Imagine there was no compile function, the text will be injected fives times which is unnecessary because we are just repeating the same old element. Also, the linking would have happened at the same time enabling watchers and degrading the performance because the watchers are reevaluated on every digest cycle to make sure views are upto date. Now by separating the two, compiling all directives first and linking them later altogether is not only performant but also cost effective because the compile function of the noop directive with ngRepeat will be triggered once whereas the linking function will be called for each iteration.

Now that we know how directives are executed so that browsers could understand their meaning without relying on HTML specification, let us look at why to use directives. Is it the ultimate answer to life, the universe, and everything?

Why use directives

By now we pretty much realized the problems that AngularJS directives are trying to solve but is it the ultimate remedy? The answer is Yes! Because the HTML language is expressive enough to create complex UI widgets and also extensible so that we, the developers, could fill in the gaps with custom tags. Probably in the near future, it will be possible through a new set of standards called Web Components.

Web Components are a collection of standards which are working their way through the W3C and landing in browsers soon. In fact they allow us to bundle markup and styles into custom HTML elements. It will allow web developers to use their HTML, CSS, and JavaScript skills to build custom elements or widgets that can be reused easily and reliably irrespective of what frameworks you use.

Even Google engineers have tried to replicate web components as Polyfills (plugins that provide technologies that developers expect the browser to provide natively) in terms of Polymer Project – a Javascript library consisting of several polyfills for various specs of Web Components APIs. Also, Mozilla has been hard at work – making web components a reality through their own JavaScript library named X-Tag to bring custom element capabilities to all modern browsers. Similar to Polymer, it also allows us to easily create elements to encapsulate common behavior or use existing custom elements to quickly get the behavior you’re looking for.

In a nutshell, AngularJS Directives is the closest thing to Web Components available at this time and we should ride this wave to get ourselves ready for the future of Web Development.

When use Directives

Apart from setting the foundation for your next ambitious web application, the AngularJS framework and directives provide lots of benefits to improve the overall development process. With the ability to extend HTML, one could design and build an entire application on top of custom elements that would be more manageable and testable. Other benefits are:

Cleaning up the jquery sphaghetti code

jQuery is a great library serving to bridge the gap between different browsers by working around various browser quirks efficiently and helping developers to focus more on building things than fixing browser issues. However, if you do not use jQuery wisely then you will soon end up writing unmanageable spaghetti code. There are many common things we often do in most web applications such as performing an action on every keystroke, adding CSS classes or removing them off an element, dynamically checking/unchecking checkboxes, binding custom events, and so on. All this is not possible without having a unique identifier to the element you are targeting in terms of ID, CSS class, data attributes, and so forth.

Take a look at the following jQuery snippet in which we simply bind a click handler on the button that posts content on Google Plus.

$('.post-to-gplus').click(function() {
  share();
  $(this).hide();
  $('#chk_gplus').prop('checked', true);
  $('#message').show();
});

The problem with this piece of code is that we have to wait until the page loads completely in the browser before we bind the click event on the button. Also the approach would not scale if we use multiple instances to share various posts. What if we make it declarative and less cluttered to handle multiple instances without modifying a bit. Here is the AngularJS version of the same.

<button ng-click='share(); shared = true;' ng-hide='shared'>
  Post to Google Plus
</button>

<input type='checkbox' ng-checked='shared'>Posted

<div class='message' ng-show='shared'>
  Your post has been shared successfully!
</div>

A few things to note here is that there is no imperative DOM manipulation involved. Post sharing, we just set the variable, shared to true to update the view automatically. We’ve then used AngularJS built-in directives, ngHide, ngChecked, and ngShow to achieve exactly the same thing, although declaratively. Notice we also got rid of the ID and Class associated to make it scalable by encapsulating everything into a custom directive.

Assembling an application like lego bricks

Writing a huge application is not a one-man show so we often work with groups of people. While working with teams, maintaining a monolithic application might sabotage the development and probably affect the schedule as well. It even makes it harder to test the whole application that way. The best way is to divide the whole application into modules/components and let each team take care of it by facilitating separation of concerns. They can work on each component independently, test it in isolation, and make it ready to be assembled later.

Suppose you are building the next generation social network named Friendular to beat Google Plus and Facebook. You can break the application into different blocks as shown in the following figure. Each of these blocks could be developed separately and does one thing only.

Breaking Monolithic application into Lego Bricks
Breaking Monolithic application into Lego Bricks

As you can see the entire application is built on top of tailor-made custom directives just like Lego bricks. This alleviates the pain points and helps to catch potentials bugs/issues at an early stage.

Supporting designers to take a plunge into markups

Developers often have to work closely with web designers to knit a well-designed application so it’s the developer’s responsibility not to mess too much with the HTML. But you can end up making a mess because of your choice of framework or library, thereby preventing designers from diving into the markups and avoiding making any further changes. Even template libraries are not much of help sometimes.

Here is a simple example to render a list of to-do items. We just iterate over a collection of to-dos and render them as an ordered list.

var html = '<ol class=”todo-list”>';

for (var I = 0; I < todos.length; I++) {
  html+= '<li class=”' + todos[I].done ? 'done' : 'undone' + '”>' +todos[I].todo + '</li>';
}

html+= '</ol>';
$('body').html(html);

This makes it really hard for any designer to modify it if he is not aware of JavaScript or jQuery. Even though it generates a string of HTML, it is not the markup designers care about.

AngularJS’s HTML as a template strategy pays off perfectly for both designers and developers in such scenario. So this will change to:

<body>
  <ol>
    <li ng-repeat='todo in todos' ng-class='{true: β€œdone”, false: β€œundone”}[todo.done]'>
      {{todo.todo}}
    </li>
  </ol>
</body>

The ngRepeat directive in AngularJS lets us iterate over an array just like for loop in JavaScript. The ngClass directive allows us to conditionally apply CSS classes so in this case, if the todo’s state is pending then it will remove the done CSS class and add undone instead – and vice versa. This will save the developer time and effort as they do not have to cherry pick the changes done somewhere else by the designer because the designer now can directly modify the same markup without getting into trouble anymore.

Gelling up well with jquery plugins

Even though AngularJS has a stripped-down version of jQuery built-in named jQLite, it does not stop you from using the original jQuery library. The jQuery ecosystem has grown rapidly because of jQuery’s ability to extend it with your own function by exposing a public API using jQuery.prototype or $.fn.

AngularJS does not discourage developers from using jQuery but helps them instead to use it in the angular world in a new way. There are thousands of jQuery plugins available online and new ones coming every day, so porting them all to the AngularJS paradigm is time consuming but would definitely reduce the lines of code which is debatable.

AngularJS enforces declarative than imperative DOM manipulation and to a certain extent the declarative approach solves many problems. But, when you use any jQuery plugin the imperative syntax is inevitable, after all, jQuery is a DOM manipulation library. Still you can encapsulate the jQuery initialization code into its own angular directive to keep it simple. So this trivial jQuery plugin:

$(document).ready(function() {
  $('#mytab').fancyTabs();
});

Will change to more readable, manageable, and declarative markup ever.

<fancy-tabs id='mytab'></fancy-tabs>

There are lots of tidbits to jQuery plugins when it comes to AngularJS so we’ll cover all those throughout the book.

Summary

We’ve peeked at the AngularJS arsenal and discussed the differences and similarities between AngularJS Directives (present) and Web Components (future). We’ve also realized the purpose of AngularJS existence and benefits it offers to Web Developers/Engineers to build powerful applications with ease. AngularJS really speeds up development and encourages us to reuse the saved time/effort to write tests. Also, learning AngularJS Directives now is a way to be ready for Web Components before they become reality.
The next chapter will unpack the AngularJS internals and things you should know about it before writing your first real world directive.

Source Code

The full source code is available on Github at https://github.com/codef0rmer/angular-directives-in-traction.