Angular 2 By Example

3.5 (11 reviews total)
By Chandermani Arora , Kevin Hennessy
  • Instant online access to over 7,500+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Getting Started

About this book

Angular 2 will help you build faster, more efficient, and more flexible cross-platform applications. Angular 2 is known for taking the pain out of JavaScript development, and enabling more organized, readable, and testable code.

This book builds three apps with varying degrees of complexity. It starts with a simple ‘Guess the Number’ game, which serves as a platform to launch you into the world of Angular. Next, you will learn to construct a popular ‘7-Minute Workout’ app, covering the building blocks of Angular. The final app, ‘Personal Trainer’ morphs the existing ‘7-Minute Workout’ into a full-fledged personal workout builder and runner, covering advanced directive building, which is the most fundamental and powerful feature of Angular.

In addition to this, you will learn about testability and the framework constructs Angular provides to effectively test your app. The book concludes by providing you with practical advice and useful tips that will come in handy as you build more and more apps with Angular.

Publication date:
November 2016
Publisher
Packt
Pages
510
ISBN
9781785887192

 

Chapter 1. Getting Started

Developing applications in JavaScript is always a challenge. Due to its malleable nature and lack of type checking, building a decent-sized application in JavaScript is difficult. Moreover, we use JavaScript for all types of processes, such as user interface (UI) manipulation, client-server interaction, and business processing/validations. As a result, we end up with spaghetti code that is difficult to maintain and test.

Libraries, such as jQuery, do a great job of taking care of various browser quirks and providing constructs that can lead to an overall reduction in the lines of code. However, these libraries lack any structural guidance that can help us when the codebase grows.

In recent years, JavaScript frameworks have emerged to manage this complexity. Many of these frameworks, including earlier versions of Angular, use a design pattern called Model-View-Controller to separate the elements of the application into more manageable pieces. The success of these frameworks and their popularity in the developer community have established the value of using this pattern.

Web development, however, is constantly evolving and a lot has changed since Angular was first introduced in 2009. Technologies such as Web Components, the new version of JavaScript (ES2015), and TypeScript have all emerged. Taken together, they offer the opportunity to build a new, forward-looking framework. And with this new framework comes a new design pattern—the component pattern.

This chapter is dedicated to understanding the component pattern and how to put it into practice as we build a simple app using Angular.

The topics that we will cover in this chapter are as follows:

  • Angular basics: We will briefly talk about the component pattern that is used to build Angular applications

  • Building our first Angular app: We will build a small game, Guess the Number!, in Angular

  • An introduction to some Angular constructs: We will review some of the constructs that are used in Angular, such as interpolation, expressions, and the data binding syntax

  • Change detection: We will discuss how change detection is managed in an Angular app

  • App initialization: We will talk about the app initialization process in Angular; this is also known as bootstrapping

  • Tools and resources: Lastly, we will provide some resources and tools that will come in handy during Angular development and debugging

 

Angular basics


Let's get started by looking at how Angular implements the component pattern.

The component pattern

Angular applications use the component pattern. You may not have heard of this pattern, but it is all around us. It is used not only in software development but also in manufacturing, construction, and other fields. Put simply, it involves combining smaller, discrete building blocks into larger finished products. For example, a battery is a component of an automobile.

In software development, components are logical units that can be combined into larger applications. Components tend to have internal logic and properties that are shielded or hidden from the larger application. The larger application then consumes these building-blocks through specific gateways, called interfaces, which expose only what is needed to make use of the component. In this way, the component's internal logic can be modified without affecting the larger application, as long as the interfaces are not changed.

Getting back to our battery example, the car consumes the battery through a series of connectors. If the battery dies, however, it can be replaced by an entirely new battery, as long as that battery has the same connectors. This means that the builder of the car does not have to worry about the internals of the battery, which simplifies the process of building the car. Even more importantly, the car owner does not have to replace his or her car every time the battery dies.

To extend the analogy, manufacturers of batteries can market them for a range of different vehicles, for example, ATVs, boats, or snowmobiles. So the component pattern enables them to realize even greater economies of scale.

Using the component pattern in web applications

As web applications continue to become more sophisticated, the need to be able to construct them out of smaller and discrete components becomes more compelling. Components allow applications to be built in a way that prevents them from becoming messes of spaghetti code. Instead, component-based design allows us to reason about specific parts of the application in isolation from the other parts, and then we can stitch the application together into a finished, whole through agreed-upon points of connection.

Also, maintenance costs are less because each component's internal logic can be managed separately without affecting the other parts of the application. And putting applications together using self-describing components makes the application easier to understand at a higher level of abstraction.

Why weren't components used before in Angular?

If this idea makes so much sense, why was the component pattern not adopted in earlier versions of Angular? The answer is that the technologies that existed when Angular was first released did not fully support the implementation of this pattern in web applications.

Earlier versions of Angular, however, made substantial steps in the direction of enabling more intelligent web application design and organization. For example, they implemented the MVC pattern, which separates an application into a model, view, and controller (you will see the use of the MVC pattern continuing within the components that we will build in Angular).

With the MVC pattern, the model is the data, the view is a web page (or a mobile app screen or even a Flash page), and the controller populates the view with data from the model. In this way, separation of concerns is achieved. Following this pattern along with an intelligent use of directives will get you pretty close to components.

So, the earlier versions of Angular allowed applications to be designed and built more logically. However, this approach was limited by the fact that the technologies used were not truly isolated. Instead, they all ended up being rendered without any true separation from other elements on the screen.

What's new that enables Angular to use this pattern?

By contrast, the newest version of Angular embraces recently emerging technologies, which make it possible to implement the component pattern more fully. These technologies include Web Components, ES2015 (the new version of JavaScript), and TypeScript. Let's discuss what each of these technologies brings to the mix that makes this possible.

Web Components

Web Components is an umbrella term that actually covers four emerging standards for web browsers:

  • Custom elements

  • Shadow DOM

  • Templates

  • HTML imports

Note

More information on Web Components can be found at http://webcomponents.org.

Let's now discuss each of these in detail:

  • Custom elements enable new types of element to be created other than the standard HTML tag names such as <div> and <p>. The ability to add custom tags provides a location on the screen that can be reserved for binding a component. In short, this is the first step towards separating a component from the rest of the page and making it possible to become truly self-contained.

  • Shadow DOM provides a hidden area on the page for scripts, CSS, and HTML. Markup and styles that are within this hidden area will not affect the rest of the page, and equally important they will not be affected by the markup and styles on other parts of the page. Our component can use this hidden area to render its display. So, this is the second step in making our component self-contained.

  • Templates are repeatable chunks of HTML that have tags that can be replaced with dynamic content at runtime using JavaScript. Many JavaScript frameworks already support some form of templating. Web Components standardize this templating and provide direct support for it in the browser. Templates can be used to make the HTML and CSS inside the Shadow DOM used by our component dynamic. So, this is the third step in making our component.

  • The final standard that makes up Web Components is HTML imports. They provide a way to load resources such as HTML, CSS, and JavaScript in a single bundle. Angular does not use HTML imports. Instead, it relies on JavaScript module loading, which we will discuss a little later in this chapter.

Angular and Web Components

Web Components are not fully supported in current web browsers. For that reason, Angular components are not strictly Web Components. It is probably more accurate to say that Angular components implement the design principles behind Web Components. They also make it possible to build components that can run on today's browsers.

Note

At the time of writing this book, Angular supports evergreen browsers, such as Chrome, Firefox, Edge, as well as IE 7 and later. It also has mobile support for Android 4.1 and later. For a list of browsers supported by Angular, visit https://github.com/angular/angular.

Therefore, throughout the rest of this book, we will focus on building Angular components and not Web Components. Despite this distinction, Angular components align closely with Web Components and can even interoperate with them. As browsers begin to support Web Components more fully, the differences between Angular components and Web Components will begin to disappear. So, if you want to begin adopting the Web Component standards of the future, Angular provides you with the opportunity to do so today.

Language support in Angular

You can develop components with ES5, but Angular enhances the ability to develop components by adding support for key features that are found in the latest languages, such as ES2015 and TypeScript.

ES2015

ES2015 is the new version of JavaScript; it was approved in June 2015. It adds many improvements to the language, which we will see throughout this book, but the two that interest us the most at this point are the following:

  • Classes

  • Module loading

Classes did not previously exist in JavaScript. The key advantage of using them, now that they do exist, is that they provide a convenient container for the code in our component.

Note

To be clear, JavaScript classes do not introduce something that is completely new. The Mozilla Developer Network (MDN) describes them as

"syntactical sugar over JavaScript's existing prototype-based inheritance. . . [that] provide a much simpler and clearer syntax to create objects and deal with inheritance."

  For more information visit https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes.

We'll ecplore these throughout the examples in this book. If you have not worked with object-oriented languages, you may not be familiar with classes, so we will cover them as we work through the examples in this chapter.

ES2015 also introduces a new approach to module loading. A module provides a way for JavaScript files to be encapsulated. When they are encapsulated, they do not pollute the global namespace and can interact with other modules in a controlled manner. We will cover modules in more details in later chapters.

Once we have our modules defined, we need a way to load them into our application for execution. Module loading allows us to select just what we need for our application from the modules that make up Angular and other components that we create or use.

Currently, a range of approaches and libraries exists to support module loading in JavaScript. ES2015 adds a new, consistent syntax for loading modules as part of the language. The syntax is straightforward and involves prefixing modules with the export keyword (or using the default export) and then using import to consume them elsewhere in our application.

ES 2015 module loading enables us to combine components into useful bundles or features that can be imported or exported within our applications. In fact, modules are at the core of Angular itself. We will see that modules are used extensively both in Angular itself and in the applications that we are building throughout this book.

Note

It is important to understand that, while Angular uses syntax that has similarities to ES2015 module-loading syntax, Angular modules (which we will discuss a little later in this chapter) are not the same as JavaScript modules. For further details on these differences see the Angular documentation at https://angular.io/docs/ts/latest/guide/architecture.html. From this point on we will be focusing on Angular modules.

Because ES2015 is not fully supported by today's browsers, we will need to convert ES2015 into ES5 in order to use features such as classes and module loading in our applications. We do this through a process called transpilation.

Transpilation is like compilation, except that instead of converting our code into a machine language as compilation does, transpilation converts one type of source code to another type of source code. In this case, it converts ES2015 to ES5. There are several tools called transpilers that enable us to do that. Common transpilers include Traceur and Babel. TypeScript (which we will discuss next) is also a transpiler, and it is the one that we will use for the examples in this book.

Once ES2015 is transpiled to ES5, we can then use a module loader such as SystemJS to load our modules. SystemJS follows the ES2015 syntax for module loading and gives us the ability to do module loading in today's browsers.

TypeScript

TypeScript was created by Microsoft as a superset of JavaScript, which means that it contains the features of ES2015 (such as classes and module loading) and adds the following:

  • Types

  • Decorators

Types allow us to mark variables, properties, and parameters in our classes to indicate that they are numbers, strings, Booleans, or various structures such as arrays and objects. This enables us to perform type checking at design time to make sure that the proper types are being used in our application.

Decorators are simple annotations that we can add to our classes using the @ symbol along with a function. They provide instructions (called metadata) for the use of our classes. In the case of Angular, decorators allow us to identify our classes as Angular components. Decorators can specify modules to be used with a component and how to implement various bindings and directives, including attaching an HTML view to the component. We will cover much more about the use of decorators as we go through this book.

Decorators form a part of the ES2017 proposal and are not part of ES2015. They were added to TypeScript as part of a collaboration between Microsoft and Google. As mentioned earlier, TypeScript compiles into ES5, so we are able to use both types and decorators in browsers that do not fully support ES2015 or the proposed standard for decorators.

Note

As mentioned previously, it is not necessary to use either ES2015 or TypeScript with Angular. However, we think that you will see the advantages of using them as we work through the examples in this book.

Putting it all together

By following the Web Component standards and adding support for ES2015 and TypeScript, Angular gives us the ability to create web applications that implement the component design pattern. These components help realize the vision behind the standards of building large-scale applications through collections of self-describing and self-contained building blocks.

We hope you will see in the examples in this book that Angular enables components to be constructed in a straightforward and declarative way that makes it easier for developers to implement them. As we proceed through the examples in this book, we will highlight where each of these technologies is being used.

Angular modules

Components are the basic building block of an Angular application. But how do we then organize these building blocks into complete applications? Angular modules provide the answer to this question. They enable us to combine our components into reusable groups of functionality that can be exported and imported throughout our application. For example, in a more sophisticated application we would want to have modules for things such as authentication, common utilities, and external service calls. At the same time, modules enable us to group features within an application in a way that allows us to load them on demand. This is called lazy loading, a topic we will cover in Chapter 4, Building Personal Trainer.

Each Angular application will have one or more modules that contain its components. Angular has introduced NgModule as a way to conveniently specify the components that make up a module. Every Angular application must have at least one of these modules—the root module.

Note

Angular itself is built as modules that we import into our application. So you will see the use of modules all over as you build Angular apps.

The basic steps to building Angular applications

To sum up: at a basic level, you will see that to develop applications in Angular, you will do the following:

  1. Create components.

  2. Bundle them into modules.

  3. Bootstrap your application.

The best way to understand Angular and the component design pattern is by seeing it in action. Hence, we are going to build our first Hello World app in Angular. This app will help you become familiar with the Angular framework and see the component design pattern in action.

Let's get started doing that.

 

The customary Hello Angular app - Guess the Number!


As our first exercise, we want to keep things simple but still showcase the framework's capabilities. Therefore, we are going to build a very simple game called Guess the Number!. The objective of the game is to guess a random computer-generated number in as few tries as possible.

This is how the game looks:

Setting up a development server

The development web server that we choose greatly depends on the platform we work on and the backend we support. However, since apps in this book target purely client-side development, any web server will do.

Our recommendation is to use live-server, a simple HTTP server with live reload capability. You can install it using Node.js. Since Node.js is available cross-platform, you can install Node.js from http://nodejs.org/.

Note

For this book, we are using Node.js version 4.4.2 and npm version 3.8.6. You can find more information about installing Node and updating npm to the latest version at https://docs.npmjs.com/getting-started/installing-node.

Once Node.js is installed, installing the live-server module and running the HTTP server is easy. Open the command line and type the following command:

npm install -g live-server

This installs live-server at the global level.

To run the server, we just navigate to the folder where the app code resides, or open the folder from where we want to serve static files. Then type this:

live-server

And that's it!

We have an HTTP server running at http://localhost:8080. It can serve files from the current directory.

Note

The live-server module does support some startup configurations. Check out the documentation at https://github.com/tapio/live-server.

Depending on the platform we are on, we can also try Python's SimpleHTTPServer module, Mongoose, or any such web server.

Let's now build Guess the Number!.

Building Guess the Number!

The standard practice while building user interfaces is to build them top-down. Start by designing the UI and then plug in the data and behavior according to your needs. With such an approach, the UI, data, and behavioral aspects of the app are all tightly coupled, which is a less than ideal situation!

With component-based design, we work differently. We start by looking at the UI and expected behavior, and then we encapsulate all of this into a building block that we call a component. This component is then hosted on our page. Within the component, we separate the UI into a view and the behavior into a class, with the appropriate properties and methods needed to support the behavior. If you are not familiar with classes, don't worry. We'll be discussing what they are in detail as we move through the example.

Okay, so let's identify the UI and behavior that we will need for our application.

Designing our first component

To determine what needs to go into our component, we will start by detailing the features that we want the app to support:

  • Generating random numbers (original)

  • Providing input for a user to guess the value (guess)

  • Tracking the number of guesses already made (noOfTries)

  • Giving the user hints to improve their guess based on their input (deviation)

  • Giving a success message if the user guesses the number correctly (deviation)

Now that we have our features, we can determine what we need to display to the user and what data we need to track. For the preceding feature set, the elements in parentheses denote the properties that will support those features and will need to be included in our component.

Note

Designing the component is a very crucial process. If it is done right, we can logically organize our application in a way that makes it understandable and easy to maintain.

While building any app, we urge you to first think about the functionality you want to offer, and then the data and behavior that can support the functionality. Lastly, think about how to build a user interface for it. This is a good practice irrespective of the library or framework you use to build your app.

The host file

Let's start by creating files for our component. We'll start by creating a directory for our application. We'll name it guessthenumber (but you can name it anything that suits you). We'll use that to add our files.

An HTML page

First, open your favorite editor and create an HTML page with the following html and script tags:

<!DOCTYPE html> 
<html> 
  <head> 
    <title>Guess the Number!</title> 
    <link href="http://netdna.bootstrapcdn.com/bootstrap/
                3.1.1/css/bootstrap.min.css" rel="stylesheet"> 
    <script src="https://unpkg.com/core-js/client/shim.min.js"></script> 
    <script src="https://unpkg.com/[email protected]"></script> 
    <script src="https://unpkg.com/[email protected]?main=browser"></script> 
    <script src="https://unpkg.com/[email protected]/lib/typescript.js">
    </script> 
    <script src="https://unpkg.com/[email protected]/dist/system.js">
    </script> 
    <script src="systemjs.config.js"></script> 
    <script> 
      System.import('app').catch(function(err){ console.error(err); }); 
    </script> 
  </head> 
  <body> 
    <my-app>Loading...</my-app> 
  </body> 
</html> 

Tip

Downloading the example code

The code in this book is available on GitHub at https://github.com/chandermani/angular2byexample. It is organized in checkpoints that allow you to follow along step by step as we build our sample projects in this book. The branch to download for this chapter is GitHub's Branch: checkpoint1.1. Look in the guessthenumber folder for the code we are covering here. If you are not using Git, download the snapshot of Checkpoint 1.1 (a ZIP file) from the following GitHub location: https://github.com/chandermani/angular2byexample/tree/checkpoint1.1. Refer to the readme.md file in the guessthenumber folder when setting up the snapshot for the first time.

Script tags

There are several things to note in this file:

  • The first five <script> tags reference the following:

    • shim: This provides ES2015 features for older browsers

    • reflect-metadata: This adds decorator support

    • zone.js: This manages change detection

    • typescript.js: This is the current version of TypeScript

    • system.js: This loads our modules

  • The next <script> tag references a JavaScript file within our application: systemjs.config.js. Be sure to add that file from the example code files. We will be discussing this file a little later. Essentially, it provides instructions to SystemJS as to which modules it should load and directs it to dynamically transpile our TypeScript files to ES5 at runtime.

  • The final <script> tag calls SystemJS to import our component directory: app.

We will discuss how the latter two script tags work together to enable module loading a little later in the chapter.

Custom elements

There is one more important tag on the page:

<my-app>Loading...</my-app> 

This tag is a custom element. It instructs Angular where to inject the component that we will be building.

The rest of the app's HTML code is self-explanatory. We reference the Twitter Bootstrap CSS in the <head> section and add a title, which is Guess the Number!, for our page.

Note

Guess the Number! and all the other apps that are part of this book have been tested against the Angular final release.

The component file

Now let's create a file for our component.

  1. Add a subdirectory to our application called app.

  2. Then, using your editor, create a file with the name guess-the-number.component.ts and place it in that subdirectory. The .ts extension identifies our file as a TypeScript file that will be compiled into ES5 at runtime.

The import statement

At the top of the page, place the following line:

import { Component }from '@angular/core'; 

This is an import statement. It tells us what modules we will be loading and using in our component. In this case, we are selecting one module that we need to load from Angular: Component. Angular has many other modules, but we load only what we need.

You'll notice that the location from which we are importing is not identified as a path or directory within our application. Instead, it is identified as @angular/core. Angular has been divided into barrel modules that are prefixed with @angular.

These barrels combine several modules that are logically related. In this case, we are indicating that we want to import the core barrel module, which in turn brings in the Component module. This naming convention ties into the loading of our modules, which we will discuss in more detail later in this chapter.

Decorators

Next, add the following block of script to your guess-the-number.component.ts file:

@Component({ 
  selector: 'my-app', 
  template: ` 
    <div class="container"> 
      <h2>Guess the Number !</h2> 
      <p class="well lead">Guess the computer generated random
         number between 1 and 1000.</p> 
      <label>Your Guess: </label> 
      <input type="number" [value]="guess" (input)="guess = 
       $event.target.value" />
      <button (click)="verifyGuess()" class="btn btn-primary btn-sm">
      Verify</button> 
      <button (click)="initializeGame()" class="btn btn-warning btn-sm">
      Restart</button> 
    <div> 
      <p *ngIf="deviation<0" class="alert alert-warning">
      Your guess is higher.</p>
      <p *ngIf="deviation>0" class="alert alert-warning">
      Your guess is lower.</p>
      <p *ngIf="deviation===0" class="alert alert-success">
      Yes! That's it.</p> 
    </div> 
      <p class="text-info">No of guesses : 
        <span class="badge">{{noOfTries}}</span> 
      </p> 
    </div> 
}) 

This is the decorator for our component and is placed directly above the class definition, which we will discuss soon. The @ symbol is used to identify a decorator. The @Component decorator has a property called selector, and you may not be surprised to see that it is set to the <my-app> tag in our HTML page. This setting tells Angular to inject this component into that tag on the HTML page.

The decorator also has a property called template, and this property identifies the HTML markup for our component. Notice the use of back ticks (introduced by ES2015) for rendering the template string over multiple lines. Alternatively, we can set a templateUrl property that would point to a separate file.

Defining the class

Now, add the following block of code to your guess-the-number.component.ts file:

export class GuessTheNumberComponent { 
  deviation: number; 
  noOfTries: number; 
  original: number; 
  guess: number; 
  constructor() { 
    this.initializeGame(); 
  } 
  initializeGame() { 
    this.noOfTries = 0; 
    this.original = Math.floor((Math.random() * 1000) + 1); 
    this.guess = null; 
    this.deviation = null; 
  } 
  verifyGuess() { 
    this.deviation = this.original - this.guess; 
    this.noOfTries = this.noOfTries + 1; 
  } 
} 

If you have been developing in ES5, the version of JavaScript that is supported in all current browsers, you may not be familiar with the use of classes here. So, we will take a few moments to walk through what makes up a class (for those of you who have developed using an object-oriented programming language, such as C# or Java, this should be familiar territory).

The class file holds the code that we will use to run our component. At the top, we give the class a name, which is GuessTheNumberComponent. Then, inside the curly braces, we have four lines that declare the properties for our class. These are similar to ES5 variables, and we will use them to hold the values that we will need to run the application (you'll notice that these are the four values that we identified when we designed our component).

What makes these properties different from standard JavaScript variables is that each property name is followed by : and number. These set the type of the property. In this case, we are indicating that each of these four properties will be set to the number type, which means we are expecting the values of all of these properties to be numbers. The ability to specify types for our properties is provided by TypeScript and is not available in standard JavaScript.

As we move down, we will see three blocks of script that have names, followed by parentheses, and then curly braces with several lines of script inside them. These are the methods for our class, and they contain the operations that our component will support. They are a lot like standard JavaScript functions.

The first of these methods is constructor(), which is a special method that will run when an instance of our component is first created. In our example, the constructor does only one thing when the class is created; it calls another method in our class, called initializeGame().

The initializeGame() method sets the starting values of the four properties in the class using the assignment operator =. We set these values to null or zero, except for original, in which we use a random number generator to create the number to be guessed.

The class holds one more method called verifyGuess(), which updates the deviation and noOfTries properties. This method is not being called from within the component class; instead, it will be called from the view, as we will see when we examine the view more closely later. You'll also notice that our methods refer to properties in the same class by prepending this to them.

The module file

As we mentioned earlier, every Angular component must be contained within an Angular module. This means that at a minimum we must add at least one Angular module file to the root of our application. We call this the root module. For a simple application like Guess the Number!, the root module may be the only module we will need. However, as an Angular application increases in size, it will often make sense to have multiple Angular module files broken down by features. We will cover that situation as we move into building more complex applications in later chapters in this book.

Let's go ahead and create our Angular module file. First, create a new file named app.module.ts in the same directory as guess-the-number.component.ts and add the following code to it:

import { NgModule }      from '@angular/core'; 
import { BrowserModule } from '@angular/platform-browser'; 
 
import { GuessTheNumberComponent }     
from './guess-the-number.component'; 
 
@NgModule({ 
    imports:      [ BrowserModule ], 
    declarations: [ GuessTheNumberComponent ], 
    bootstrap:    [ GuessTheNumberComponent ] 
}) 
export class AppModule { } 

The first two statements import NgModule and BrowserModule. Notice that, while NgModule is being imported from @angular/core, BrowserModule is being imported from a different module: @angular/platform-browser. What's significant here is that the import is not coming from @angular/core but from a separate module that is specific to browser-based applications. This is a reminder that Angular can support devices other than browsers, such as mobile devices, hence the need to place BrowserModule into a separate module.

The other import in this file is our component GuessTheNumberComponent, which we just built. If you go back to that component you will notice that we added export in front of the class definition, which means we are using module loading within our own application.

We next define a new component AppModule. This component looks different from GuessTheNumberComponent, which we just defined. There is nothing in the class itself other than a few imports and a decorator: @ngModule. We can use this decorator to configure the module in our application. We first add imports, which in this case include the BrowserModule. As the name suggests, this module will provide the functionality needed to run our application in a browser. The next property is declarations and with that property we provide an array of the components that will be used in our application. In this case, we have just one component: GuessTheNumberComponent.

Finally, we set the bootstrap property. This indicates the first component that will be loaded when our application starts up. Again this is the GuessTheNumberComponent.

With this configuration in place, we are now ready to bootstrap our component.

Bootstrapping

The class definition for GuessTheNumberComponent operates as a blueprint for the component, but the script inside it does not run until we have created an instance of the component. In order to run our application then, we need something in our application that creates this instance. The process of doing that requires us to add code that bootstraps our component.

In the app subdirectory, create another file named main.ts and add the following code to it:

import { platformBrowserDynamic }    
from '@angular/platform-browser-dynamic'; 
import { AppModule } from './app.module'; 
const platform = platformBrowserDynamic(); 
platform.bootstrapModule(AppModule); 

As you can see, we are first importing the platformBrowserDynamic module from @angular/platform-browser-dynamic. Like the import of BrowseModule in the appModule file, this import is specifically for browser-based applications.

Next we add an import of our AppModule, which we have just defined.

Finally, we assign platformBrowserDynamic(), which we just imported, to a constant: platform. Then we call its bootstrapModule method with our AppModule as a parameter. The bootstrapModule method then creates a new instance of our AppModule component, which in turn initializes our GuessTheNumberComponent, which we have marked as the component to bootstrap. It does that by calling the component's constructor method and setting the starting values for our game.

We will discuss in greater detail how this bootstrap method fits into the entire process of app initialization a little later in this chapter.

We're up-and-running!

Well, the app is complete and ready to be tested! Navigate to the directory where the file is located and type this:

live-server

The app should appear on your browser.

Note

If you are having trouble running the app, you can check out a working version available on GitHub at https://github.com/chandermani/angular2byexample. If you are not using Git, download the snapshot of Checkpoint 1.1 (a ZIP file) from the following GitHub location: https://github.com/chandermani/angular2byexample/tree/checkpoint1.1. Refer to the readme.md file in the guessthenumber folder when setting up the snapshot for the first time.

If we glance at our component file now, we should be mightily impressed with what we have achieved with these 43 lines. We are not writing any code to update the UI when the application is running. Still, everything works perfectly.

 

Digging deeper


To understand how this app functions in the Angular context, we need to delve a little deeper into our component. While the class definition in the component is pretty simple and straightforward, we need to look more closely at the HTML in the template that is inside the @Component decorator to understand how Angular is working here. It looks like standard HTML with some new symbols, such as [ ], ( ), {{, and }}.

In the Angular world, these symbols mean the following:

  • {{ and }} are interpolation symbols

  • [ ] represents property bindings

  • ( ) represents event bindings

Clearly, these symbols have some behavior attached to them and seem to be linking the view HTML and component code. Let's try to understand what these symbols actually do.

Interpolation

Look at this HTML fragment from the Guess the Number! code:

<p class="text-info">No of guesses :  
  <span class="badge">{{noOfTries}}</span> 
</p> 

The term noOfTries is sandwiched between two interpolation symbols. Interpolation works by replacing the content of the interpolation markup with the value of the expression (noOfTries) inside the interpolation symbol. In this case, noOfTries is the name of a component property. So the value of the component property will be displayed as the contents inside the interpolation tags.

Interpolations are declared using this syntax: {{expression}}. This expression looks similar to a JavaScript expression but is always evaluated in the context of the component. Notice that we did not do anything to pass the value of the property to the view. Instead, the interpolation tags read the value of the property directly from the component without any need for additional code.

Tracking changes in the number of tries

Another interesting aspect of interpolation is that changes made to component properties are automatically synchronized with the view. Run the app and make some guesses; the noOfTries value changes after every guess and so does the view content:

Interpolation is an excellent debugging tool in scenarios where we need to see the state of the model. With interpolation, we don't have to put a breakpoint in code just to know the value of a component property. Since interpolation can take an expression, we can pass a component's method call or a property and see its value.

Expressions

Before going any further, we need to spend a few moments understanding what template expressions are in Angular.

Template expressions in Angular are nothing but pieces of plain JavaScript code that are evaluated in the context of the component instance associated with the template instance in which they are used. But as the documentation at https://angular.io/docs/ts/latest/guide/template-syntax.html#template-expressions makes it clear, there are some differences:

  • Assignment is prohibited, except in event bindings

  • The new operator is prohibited

  • The bitwise operators | and & are not supported

  • Increment and decrement operators, ++ and --, aren't supported

  • Template expression operators, such as | and ?. add new meanings

In the light of our discussion on component-based design, you probably won't be surprised to learn that the documentation also makes some more things clear; template expressions cannot:

  • Refer to anything in the global namespace

  • Refer to a window or document

  • Call console.log

Instead, these expressions are confined to the expression context, which is typically the component instance supporting a particular template instance.

However, these limitations do not stop us from doing some nifty stuff with expressions. As we can see in the following examples, these all are valid expressions:

// outputs the value of a component property 
{{property}} 
 
// adds two values 
{{ 7 + 9 }} 
 
//outputs the result of boolean comparison. Ternary operator 
{{property1 >=0?'positive': 'negative'}} 
 
//call a component's testMethod and outputs the return value 
{{testMethod()}} 

Note

Having looked into expressions, we strongly advise you to keep your expressions simple, thus keeping the HTML readable. The *ngIf="formHasErrors()" expression is always better than * ng-if="name==null || email==null || emailformatInValid(email) || age < 18". So, when an expression starts to become complex, move it into a method in your component.

The safe navigation operator

Before we move on there is one other expression that we should touch on: the Angular safe navigation operator (?.). This operator provides a convenient way to check for null values in lengthy property paths like so:

{{customer?.firstName }} 

If the safe navigation operator finds a null value (here the customer), it stops processing the path but lets the application continue running. Without it, the application will crash when it reaches anything after the first null (here the customer name) and the view will not display. The safe navigation operator is especially helpful in situations where you are loading data asynchronously and it might not be immediately available to the view. The safe navigation operator will prevent the application from crashing and then load the data when it is available.

Data binding

Learning interpolation and expressions was easy; now let's look at another framework construct that is being used by our sample app-data binding. We will be covering data binding in far more detail in the upcoming chapters. At this point, we will just touch briefly on the bindings that are used in the sample app we are building.

Property binding

If we look through the HTML for the view, we will see several places where square brackets [ ] are used. These are property bindings.

Let's look at the first of the bindings that we created:

<input type="number" [value]="guess" (input)="guess =    $event.target.value" />

This binding works by linking the value of the guess property in our component class to the value of the input field in the view. The binding is dynamic; so, as the value of the guess property changes, the value of the input field will be synchronized to the same value. And, we do not have to write any code to do that.

At the outset, when we initialize the game, this property is set to null in the initialization method of the component class, so we will not see anything in the input field. However, as the game progresses, this number will be updated with the value of the guess as it changes.

Event binding

Looking again at the HTML view, we find several places where parentheses ( ) appear. These are event bindings.

Let's look at the HTML code line that we created for the first of these event bindings. It should be familiar since the event binding is on the same tag that we first looked at for property binding: the input tag:

<input type="number" [value]="guess" (input)="guess =    $event.target.value" />

In this case, the input event of the input element is bound to an expression. The expression sets the guess property in our component class to $event.target.value, which is the value being entered by the user. Behind the scenes, when we use this syntax, Angular sets up an event handler for the event that we are binding to. In this case, the handler updates the guess property in our component class whenever the user enters a number in the input field.

There are a couple of other places in your code where the ( ) parentheses appear:

<button (click)="verifyGuess()" class="btn btn-primary btn-sm">Verify</button>
<button (click)="initializeGame()" class="btn btn-warning    btn-sm">Restart</button>

These two event bindings tie the click events for the buttons on the screen to methods in our component. So in this case, behind the scenes, Angular sets up event handlers that bind directly to the methods in our component. When the Verify button is clicked, the verifyGuess method is called, and when the Restart button is clicked, the initializeGame method is called.

As you work through the samples in this book, you will see many places where the [] tags for property bindings are combined with the () tags for events. In fact, this pairing is so common that, as we will see later, Angular has come up with a shorthand syntax to combine these tags into one.

Structural directives

Next, we'll examine something that looks similar to data binding but incorporates an Angular feature we have haven't seen before: structural directives:

<div>
  <p *ngIf="deviation<0" class="alert alert-warning"> Your guess is higher.</p> 
  <p *ngIf="deviation>0" class="alert alert-warning"> Your guess is lower.</p>
  <p *ngIf="deviation===0" class="alert alert-success"> Yes! That"s it.</p> 
</div> 

*ngIf inside the <p> tags is the NgIf structural directive. Structural directives allow us to manipulate the structure of DOM elements. The NgIf directive removes or adds DOM elements based on the result of an expression that is assigned to it.

Note

The asterisk * in front of ngIf is a simplified syntax that Angular, under the hood, expands into an HTML5 <template>. We'll be learning a lot more about this syntax and about structural directives in the next chapter.

In this case we are using NgIf with a simple expression, similar to the types of expression we saw with interpolation. The expression resolves to either true or false based on the value of the guess being made and its relation (higher, lower, or equal) to the correct number. It then assigns that result to NgIf, which will either add the DOM element if the result is true or remove it if it is false.

 

Revisiting our app


So now that we have looked more closely at what makes up our view, let's take another look at our app when it is up-and-running. When we run our app, Angular binding starts up once the browser has rendered the raw HTML in our view. The framework then compiles this view template and, in the process, sets up the necessary binding. Next, it does the necessary synchronization between our component class and the view template that produces the final rendered output. The following screenshot depicts the transformations that happen to the view template after data binding is done for our app:

We can ourselves see the untransformed view template of the app (what is shown on the left-hand side of the preceding screenshot) by removing the three *ngIf directives and the expressions assigned to them from the paragraphs below the input box and refreshing the app in the browser.

Angular differs from other template frameworks, in that these bindings between a component and its view are live. Changes made to the properties of the component update the view. Angular never regenerates the HTML; it just works on the relevant part of the HTML and updates only the HTML elements that need to change as component properties change. This data binding capability makes Angular an exceptional view templating engine too.

 

Looking at how our code handles updates


If we go back and look at the code for our class, we will see that the properties and methods in the class do not directly reference the view. Instead, the methods simply operate on the properties in the class. As a consequence, the code for our class is more readable, hence more maintainable (and of course, testable).

So far, we have discussed how Angular updates the view based on changes in a component's properties. This is an important concept to understand as it can save us from countless hours of debugging and frustration. The next section is dedicated to learning about change detection and how these updates are managed.

 

Maintaining the state


First, let's look at how we maintain the state in our Angular application. Since Angular apps are dynamic and not static, we need to understand the mechanisms that are used to make sure that these dynamic values are kept up-to-date as the data in an application gets updated. For example, in our application, how does the number of guesses get updated on the screen? How does the application decide to display the correct message about whether the guess is correct based on the user input?

Component as the container for the state

Since we have been emphasizing so far that Angular uses the component design pattern, you will probably not be surprised to know that the basic container for the application state is the component itself. This means that when we have a component instance, all the properties in the component and their values are available for the template instance that is referenced in the component. At a practical level, this means that we can use these values directly in expressions and bindings in the template without having to write any plumbing code to wire them up.

In the sample app, for example, to determine what message to display, we can use deviation directly in the template expression. Angular will scan our component to find a property with that name and use its value. The same is true for noOfTries; Angular will look for the value of this property within our component and then use it to set its value in the interpolation within the template. We don't have to write any other code:

template: ` 
............. 
  <div>
    <p *ngIf="deviation<0" class="alert alert-warning"> Your guess is higher.</p>
    <p *ngIf="deviation>0" class="alert alert-warning"> Your guess is lower.</p>
    <p *ngIf="deviation===0" class="alert alert-success"> Yes! That's it.</p></div> 
    <p class="text-info">No of guesses : 
      <span class="badge">{{noOfTries}}</span> 
    </p> 
</div>
` 

Change detection

So how does Angular keep track of changes in our component as it runs? So far, it appears as if this is all done by magic. We just set up our component properties and methods, and then we bind them to the view using interpolation along with property and event binding. Angular does the rest!

But this does not happen by magic, of course, and in order to make effective use of Angular, you need to understand how it updates these values as they change. This is called change detection, and Angular has a very different approach to doing this than what previously existed.

If you use the debugger tool in your browser to walk through the application, you will see how change detection works. Here, we are using Chrome's developer tools and setting a watch for the noOfTries property. If you place a breakpoint at the end of the verifyGuess() method, you will see that when you enter a guess, the noOfTries property is first updated as soon as you hit the breakpoint, like this:

Once you move past the breakpoint, the display on the screen updates with the correct number of guesses, as seen in the following screenshot:

What is really going on under the hood is that Angular is reacting to events in the application and using change detectors, which go through every component to determine whether anything has changed that affects the view. In this case, the event is a button click. The event generated by the button click calls the verifyGuess() method on the component that updates the noOfTries property.

That event triggers the change detection cycle, which identifies that the noOfTries property that is being used in the view has changed. As a result, Angular updates the element in the view that is bound to noOfTries with the new value of that property.

As you can see, this is a multistep process where Angular first updates the components and domain objects in response to an event, then runs change detection, and finally rerenders elements in the view that have changed. And, it does this on every browser event (as well as other asynchronous events, such as XHR requests and timers). Change detection in Angular is reactive and one way.

This approach allows Angular to make just one pass through the change detection graph. It is called one-way data binding, and it vastly improves the performance of Angular.

Note

We'll be covering Angular change detection in depth in Chapter 8, Some Practical Scenarios. For a description of this process by the Angular team, visit https://vsavkin.com/two-phases-of-angular-2-applications-fda2517604be#.fabhc0ynb.

 

Initializing the app


We touched on app initialization earlier when we created the app.module.ts and main.ts files. The first file wraps our application in a module and the second file bootstraps that module. Now we will take a more detailed look at the initialization process.

Loading the modules needed by our application

Let's go back to the index.html page again and take a look at the following script tags on this page:

<script src="https://unpkg.com/[email protected]/dist/system.js"></script> 
<script src="systemjs.config.js"></script> 

The first tag indicates that we will be using a JavaScript library called SystemJS in our application. The second tag references a file within our application that sets the configuration for SystemJS.

As we mentioned earlier, ES2015 introduced a new syntax for module loading. One attractive feature of ES2015 module loading syntax is that it allows for modules to be loaded selectively and asynchronously. We will be using module loading throughout our application.

TypeScript supports the ES2015 module loading syntax, and SystemJS allows us to add module loading to applications that run ES5. Putting the two together:

  • TypeScript will transpile (compile) our application's components to ES5

  • SystemJS will load them as ES5 modules

As part of this process, each of our TypeScript files will be compiled to a SystemJS module. SystemJS will then load all the related dependencies and when requested the module itself.

Note

Other module loaders exist, including Webpack, so you are not limited in your choice of module loaders to SystemJS. For more information on using Webpack with Angular refer to the following documentation on the Angular site: https://angular.io/docs/ts/latest/guide/webpack.html.

Open systemjs.config.js. You will see that it contains mappings that indicate where SystemJS should look for the files that are needed in our application:

map : { 
    'app': 'app', 
    'rxjs': 'https://unpkg.com/[email protected]', 
    '@angular/common': 'https://unpkg.com/@angular/[email protected]', 
    '@angular/compiler': 'https://unpkg.com/@angular/[email protected]', 
    '@angular/core': 'https://unpkg.com/@angular/[email protected]', 
    '@angular/platform-browser': 'https://unpkg.com/@angular/
                                  [email protected]', 
    '@angular/platform-browser-dynamic': 'https://unpkg.com/@angular/
     [email protected]' 
}, 

First, we map our own application, app, to the directory in which it resides. Then we add mappings for RxJS and several Angular modules. They are being downloaded from a content delivery network (CDN), the Node Package Manager (https://unpkg.com/#/) CDN. As you can see, we are using the @ notation with the Angular modules. As we mentioned before, this means we will be importing Angular barrels containing multiple modules.

Note

The module bundles that Angular identifies as barrels are referred to as scoped packages in NPM. For a description of how Angular is using NPM scoped packages, visit https://www.reddit.com/r/Angular2/comments/4hk0f8/the_angular2_team_is_changing_the_repository_on/.

Next, we identify the packages that we will be importing and their main entry points. In the case of our app package, we indicate that main.ts will be the entry point and ts will be the default extension since we are using TypeScript for it. Then we identify the specific Angular @barrels that we will be using in our application:

packages:{ 
    'app':  { main: 'main.ts',  defaultExtension: 'ts' }, 
    '@angular/common': { main: 'bundles/common.umd.js',
                         defaultExtension: 'js' }, 
    '@angular/compiler': { main: 'bundles/compiler.umd.js',
                           defaultExtension: 'js' }, 
    '@angular/core': { main: 'bundles/core.umd.js',
                       defaultExtension: 'js' }, 
    '@angular/platform-browser': { main: 'bundles/platform-browser.umd.js',
                                   defaultExtension: 'js' }, 
    '@angular/platform-browser-dynamic': { main: 
    'bundles/platform-browser-dynamic.umd.js', defaultExtension: 'js' }, 
}, 

These packages will be all we need to run our application. As you move to more sophisticated applications, more packages will be required. But you only need to add what is required to get the application running and this is what we are doing here. The flexibility to select just the packages that you need helps to minimize the size of the download, always a good thing for performance.

The file also contains the following script that directs SystemJS to transpile our TypeScript files:

transpiler: 'typescript', 
typescriptOptions: { 
    emitDecoratorMetadata: true 
} 

Note

This script will transpile our TypeScript files in the browser, which we would typically not do in a production app. Also, in order to keep the setup of our application as simple as possible, we are downloading the Angular modules and other libraries on-the-fly as the browser loads. In a production application, we would move both these steps into a build process that takes place before the application is launched in the browser. This will reduce the download size of the application and improve performance. We will be exploring setting up such a build process in Chapter 2, Building Our First App – 7 Minute Workout.

We then implement the module loading for our app by adding the following script to our index.html file:

system.import('app').catch(function(err){ console.error(err); }); 

The parameter being passed to our import statement app is the location of our application, which in this case is the app directory. Because we have indicated in systemjs.config.js that main.ts will be the entry point for our app, SystemJS will look for that file in the app directory when the application first starts.

Bootstrapping our app

The next step in the initialization process is to bootstrap our application. As the entry point for our app, main.ts does that by executing the following code:

platform.bootstrapModule(AppModule); 

Not surprisingly, we are bootstrapping AppModule. As we already know, bootstrapping instantiates GuessTheNumberComponent because it has been assigned to the bootstrap property within AppModule.

Note

This makes GuessTheNumberComponent the root component for our application. While our app has only one component, every Angular application typically starts off with one root component.

We identify where this component will appear using the following syntax in our index.html file:

<my-app>Loading...</my-app>  

As you might recall, the @Component decorator for our component identifies the component's selector:

@Component({ 
  selector: 'my-app' 

Taken together, these indicate to Angular that when our page is loaded, it needs to bind our component to the my-app tag in index.html. Note that here we are using a custom element based on the Web Components standard.

So, this starts the bootstrapping process, which continues as follows:

  • Angular scans our component definition and imports the modules that we have identified in the import statement of our component along with its related dependencies. These are the modules that we discussed earlier.

  • It compiles the HTML view, starting from where the my-app tag is declared. In this compilation process, the framework traverses the template, looks for all interpolations, and sets up the binding between the view and our class.

  • Post compilation, it links the view and our component class where changes are synced across the model and viewed in real time as we interact with the app.

 

Tools


Tools make our lives easy, and we are going to share some tools that will help you with different aspects of Angular development, from code writing to debugging:

  • Augury ( https://augury.angular.io/ ): This is a Chrome Dev Tools extension for debugging Angular applications. While the developers of the tool, rangle.io, indicate that it should be treated as a preview, it does support the Angular final release.

  • Browser developer console: All current browsers have excellent capabilities when it comes to JavaScript debugging. Since we are working with JavaScript, we can put in breakpoints, add a watch, and do everything that is otherwise possible with JavaScript. Remember that a lot of errors with code can be detected just by looking at the browser's console window.

  • JSFiddle and Plunker: JSFiddle (http://jsfiddle.net/) and Plunker (http://plnkr.co/) are excellent playgrounds for trying out HTML, CSS, and JavaScript code. These tools also have great versioning and sharing capabilities that can come in handy if we want someone's help.

  • IDE extensions: Many of the popular IDEs on the market have plugins/extensions that make Angular development easy for us. Examples include:

  • Visual Studio Code: This is a brand new IDE that Microsoft has come up with (https://code.visualstudio.com/). It provides excellent IntelliSense and code completion support for Angular and TypeScript. Visual Studio 2015 (https://www.visualstudio.com/) also includes support for Angular and TypeScript.

  • The Angular community is also developing CLI tools (https://cli.angular.io/) with the goal of taking the developer from the initial project setup all the way to the final deployment. We'll cover using Angular CLI in Chapter 8, Some Practical Scenarios.

  • Component vendors are starting to offer support for Angular as well. For example, Telerik has released Kendo UI for Angular: http://www.telerik.com/kendo-angular-ui/.

 

Resources


Angular is a new framework, but already a vibrant community is starting to emerge around it. Together with this book, there are also blogs, articles, support forums, and plenty of help. Some of the prominent resources that will be useful are explained as follows:

That's it! The chapter is complete and it's time to summarize what you've learned.

 

Summary


The journey has started and we have reached the first milestone. Despite this chapter being named Getting Started, we have covered a lot of concepts that you will need to know in order to understand the bigger picture. Your learning was derived from our Guess the Number! app, which we built and dissected throughout the chapter.

You learned how Angular implements the component design pattern using the emerging standards for Web Components, along with the latest versions of JavaScript and TypeScript. We also reviewed some of the constructs that are used in Angular, such as interpolation, expressions, and the data binding syntax. Finally, we took a look at change detection and app initialization.

The groundwork has been laid, and now we are ready for some serious app development on the Angular framework. In the next chapter, we will start working on a more complex exercise and expose ourselves to a number of new Angular constructs.

About the Authors

  • Chandermani Arora

    Chandermani Arora is a software craftsman, with love for technology and expertise on web stack. With years of experience, he has architected, designed, and developed various solutions for Microsoft platforms. He has been building apps on Angular 1 since its early days. Having a passion for the framework every project of his has an Angular footprint.

    He tries to support the platform in every possible way by writing blogs on various Angular topics or helping fellow developers on StackOverflow, where he is an active member on the Angular channel. He also authored the first edition of this book.

    Browse publications by this author
  • Kevin Hennessy

    Kevin Hennessy is a Senior Software Engineer with Applied Information Sciences. He has 20 years' experience as a developer, team lead, and solutions architect, working on web-based projects, primarily using the Microsoft technology stack. Over the last several years, he has presented and written about single-page applications and JavaScript frameworks, including Knockout, Meteor, and Angular. He has spoken about Angular at the All Things Open Conference. 

    Browse publications by this author

Latest Reviews

(11 reviews total)
Very thorough and great description
Los materiales son muy buenos
The preface says the book is for people "with no prior experience". At the time I was looking for Angular 2 books with a lot of info about Observables. I should have looked at the contents more closely.