Chapter 1. Introduction to AngularJS

Google’s AngularJS is an all-inclusive JavaScript model-view-controller (MVC) framework that makes it very easy to quickly build applications that run well on any desktop or mobile platform. In a very short period of time, AngularJS has moved from being an unknown open source offering to one of the best known and most widely used JavaScript client-side frameworks offered. AngularJS 1.3 and greater combined with jQuery and Twitter Bootstrap give you everything you need to rapidly build HTML5 JavaScript application frontends that use REST web services for the backend processes. This book will show you how to use all three frontend components to harness the power of REST services on the backend and quickly build powerful mobile and desktop applications.

JavaScript Client-Side Frameworks

JavaScript client-side applications run on the user’s device or PC, and therefore shift the workload to the user’s hardware and away from the server. Until fairly recently, server-side web MVC frameworks like Struts, Spring MVC, and ASP.NET were the frameworks of choice for most web-based software development projects. JavaScript client-side frameworks, however, are sustainable models that offer many advantages over conventional web frameworks, such as simplicity, rapid development, speed of operation, testability, and the ability to package the entire application and deploy it to all mobile devices and the Web with relative ease. You can build your application one time and deploy and run it anywhere, on any platform, with no modifications. That’s powerful.

AngularJS makes that process even faster and easier. It helps you build frontend applications in days rather than months and has complete support for unit testing to help reduce quality assurance (QA) time. AngularJS has a rich set of user documentation and great community support to help answer questions during your development process. Models and views in AngularJS are much simpler than what you find in most JavaScript client-side frameworks. Controllers, often missing in other JavaScript client-side frameworks, are key functional components in AngularJS.

Figure 1-1 shows a diagram of an AngularJS application and all related MVC components. Once the AngularJS application is launched, the model, view, controller, and all HTML documents are loaded on the user’s mobile or desktop device and run entirely on the user’s hardware. As you can see, calls are made to the backend REST services, where all business logic and business processes are located. The backend REST services can be located on a private web server or in the cloud (which is most often the case). Cloud REST services can scale from a handful of users to millions of users with relative ease.

Alt Text
Figure 1-1. Diagram of an AngularJS MVC application

Dependency Injection

Dependency injection (DI) is a design pattern where dependencies are defined in an application as part of the configuration. Dependency injection helps you avoid having to manually create application dependencies. AngularJS uses dependency injection to load module dependencies when an application first starts. The app.js code in the previous section shows how AngularJS dependencies are defined.

As you can see, two dependencies are defined as needed by the helloWorldApp application at startup. The dependencies are defined in an array in the module definition. The first dependency is the AngularJS ngRoute module, which provides routing to the application. The second dependency is our controller module, helloWorldControllers. We will cover controllers in depth later, but for now just understand that controllers are needed by our applications at startup time.

Dependency injection is not a new concept. It was introduced over 10 years ago and has been used consistently in various application frameworks; DI was at the core of the popular Spring framework written in Java. One of its main advantages is that it reduces the need for boilerplate code, writing of which would normally be a time-consuming process for a development team.

Dependency injection also helps to make an application more testable. That is one of the main advantages of using AngularJS to build JavaScript applications. AngularJS applications are much easier to test than applications written with most JavaScript frameworks. In fact, there is a test framework that has been specifically written to make testing AngularJS applications easy. We will talk more about testing at the end of this chapter.

HTML5 Mode

The complete app.js file is shown next. The last line in app.js ($locationProvider.html5Mode(false).hashPrefix('!');) uses the locationProvider service. This line of code turns off the HTML5 mode and turns on the hashbang mode of AngularJS. If you were to turn on HTML5 mode instead by passing true, the application would use the HTML5 History API. HTML5 mode also gives the application pretty URLs like /someAppName/blogPost/5 instead of the standard AngularJS URLs like /someAppName/#!/blogPost/5 that use the #!, known as the hashbang.

/* chapter1/app.js complete file */

'use strict';
/* App Module */

var helloWorldApp = angular.module('helloWorldApp', [
  'ngRoute',
  'helloWorldControllers'
]);

helloWorldApp.config(['$routeProvider', '$locationProvider',
  function($routeProvider, $locationProvider) {
    $routeProvider.
      when('/', {
         templateUrl: 'partials/main.html',
         controller: 'MainCtrl'
      }).when('/show', {
         templateUrl: 'partials/show.html',
         controller: 'ShowCtrl'
});
$locationProvider.html5Mode(false).hashPrefix('!');
}]);

HTML5 mode can provide pretty URLs, but it does require configuration changes on the web server in most cases. The changes are different for each individual web server, and can differ for different server installations as well. HTML5 mode also handles URL changes in a different way, by using the HTML History API for navigation.

Using HTML5 mode is just a configuration change in AngularJS, and we won’t cover the needed server changes in this book as our focus is on AngularJS. The AngularJS site has documentation on the changes needed for all modern web servers when HTML5 mode is enabled. Using this mode has some benefits, but we will stick with hashbang mode in our chapter exercises.

Hashbang mode is used to support conventional search engines that don’t have the ability to execute JavaScript on Ajax sites like those built with AngularJS. When a conventional search engine searches a site built with AngularJS that uses hashbangs, the search engine replaces the #! with ?_escaped_fragment_=. Conventional search engines expect the server to have HTML snapshots at the location where _escaped_fragment_= is configured to point. HTML snapshots are merely copies of the HTML rendered version of the website or application.

Modern Search Engines

Fortunately, modern search engines have the ability to execute JavaScript, as announced by Google in a news release on May 23, 2014. Hashbang mode also allows AngularJS applications to store Ajax requested pages in the browser’s history. That process often simplifies browser bookmarks.

Controller Business Logic

The following code shows the contents of the controllers.js file. At the start of the file we define the helloWorldController module. We then define two new controllers, MainCtrl and ShowCtrl, and attach them to the helloWorldController module. Business logic specific to the MainCtrl controller is defined inside that controller. Likewise, business logic specific to the ShowCtrl controller is defined inside the ShowCtrl controller. Notice that $scope is injected into both controllers. The $scope that is injected into each controller is specific to that controller and not visible to other controllers:

/* chapter1/controllers.js */

'use strict';
/* Controllers */

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

helloWorldControllers.controller('MainCtrl', ['$scope', 
function MainCtrl($scope) {
  $scope.message = "Hello World";
}]);

helloWorldControllers.controller('ShowCtrl', ['$scope', 
function ShowCtrl($scope) {
  $scope.message = "Show The World";
}]);

As you can see, we are now using the model to populate the messages that get displayed in the templates. The following code shows the modified templates that use the newly created model values. The line $scope.message = "Hello World" in the MainCtrl controller is used to create a property named message that is added to the scope (which holds the model attributes). We then use the double curly braces markup ({{}}) inside the main.html template to gain access to and display the value assigned to $scope.message:

<!-- chapter1/main.html -->

<div>{{message}}</div>

Using double curly braces is AngularJS’s way of displaying scope properties in the view. The double curly braces syntax is actually part of the built-in AngularJS template language.

Likewise, we use the value assigned to the message property with the line $scope.message = "Show The World" in the ShowCtrl controller to populate the message displayed in the show.html template. We use the double curly braces markup inside the show.html template as before to gain access to and display the model property:

<!-- chapter1/show.html -->

<div>{{message}}</div>

Testing AngularJS Applications

In recent years continuous integration (CI) build tools such as Travis CI, Jenkins, and others have risen in popularity and usage. CI tools have the ability to run test scripts during a build process and give immediate feedback by way of test results. CI tools help to automate the process of testing software and can often alert developers of software defects as soon as they occur.

There are two types of AngularJS tests that integrate well with CI tools. The first type of testing is unit testing. Most developers are familiar with unit testing; they can often identify software defects early in the development process by testing small units of code. The second type of testing is end-to-end (E2E) testing. E2E testing helps to identify software defects by testing how software components connect and interact.

There are many testing tools used for unit testing AngularJS applications. Two of the most popular are Karma and JS Test Driver. Karma, however, is quickly becoming the top choice for AngularJS development teams. The most popular E2E test tool for end-to-end testing of AngularJS applications is a new tool called Protractor. Both tools integrate well with CI build tools.

Large AngularJS development teams will find testing AngularJS applications with continuous integration tools to be a huge time-saver. Often a failed CI test is the first indication of a defect for large teams. Small teams will also see many advantages to CI-based testing. AngularJS developers should always develop both unit tests and end-to-end tests whenever possible.

Throughout this book, we will cover both unit testing and end-to-end testing. We will use both Karma and JsTestDrive for unit testing, and we will use Protractor for E2E testing.