Angular 6 by Example - Third Edition

4.1 (9 reviews total)
By Chandermani Arora , Kevin Hennessy
  • Instant online access to over 8,000+ 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 helps you build faster, efficient, and flexible cross-platform applications. Creating complex and rich web applications, with a lighter resource footprint, has never been easier or faster. Angular is now at release 6, with significant changes compared to previous versions.

In this third edition of Angular by Example, you’ll build three apps with varying degrees of complexity. The book 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 develop 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 apps with Angular.

Publication date:
June 2018
Publisher
Packt
Pages
504
ISBN
9781788835176

 

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 code-base  /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 has changed a lot 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
  • 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 their 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 the component 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 https://www.webcomponents.org/introduction

Let's now discuss each of these in detail:

  • Custom elements enable new types of DOM elements to be created other than the standard HTML tags such as <div> and <p>.  You will see the use of these custom elements throughout this book. For example, the application that we are building in this chapter will have a root element named <app-root>, but you can give this element any name you like.  Individual components will also use custom elements. For example, in the following chapters we are building a more sophisticated application that breaks the screen down into components. The header of the page will use a custom element <abe-header>  to display its content (the prefix abe is unique to our application and helps to avoid naming collisions with native HTML elements or custom elements in other apps). 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 importantly 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 fragments of HTML that do not initially render in a web page, but can be activated 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 in today's browsers.

Note

At the time of writing, Angular supports evergreen browsers, such as Chrome, Firefox, Safari, and Edge, as well as IE 9 and above. It also has support for Android and IOS. For a list of browsers supported by Angular, visit https://angular.io/guide/browser-support.

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 inter-operate 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 (the version of JavaScript supported in all current browsers), 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 offer a simple, clear syntax that we can use to create convenient containers for the code in our components. As you will find when you begin working on the applications in this book. Classes also provide a convenient shorthand designation for our components that makes it easier to stitch them together with each other through things such as dependency injection.

Note

To be clear, JavaScript classes do not introduce something that is completely new. The Mozilla Developer Network (MDN) describes them as primarily syntactical sugar over JavaScript's existing prototype-based inheritance.  For more information visit https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes.

We'll explore classes 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. 

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/guide/architecture#ngmodules-vs-javascript-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. Alternatively, we can  use a module bundler such as webpack to load and combine our modules. For the projects in this book we will be using webpack to load, bundle, and deploy the modules in our applications.

Note

Since the release of ES2015, the schedule for releases of new versions of ECMAScript (the official name for JavaScript) is on an annual basis—so we now have ES2016 and ES2017 and will soon have ES2018.  Since the features that we are highlighting throughout this book were first introduced in ES2015, we will be referring to ES2015 instead of any of the newer versions. The newer versions, however, are fully compatible with the language features that we are highlighting here and elsewhere in the book.

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 also enable us to specify a custom element to which to bind our component and to identify a template that adds an HTML view to our component. We will cover much more about the use of decorators as we go through this book.

Decorators  are not part of ES2015, but are part of a proposal to include them in the JavaScript language in the future. 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 that 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 that 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:

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 that you use to build your app.

Developing our first component

Now that we have a design for our first component, we’ll start developing it using the Angular Command Line Interface (Angular CLI). The Angular CLI enables us to start building Angular applications and deploying them through a series of console commands. We’ll be covering the Angular CLI in greater detail in future chapters. For now, we will install it and use it to generate a basic application as the beginning point for our first component.

To use the Angular CLI you must first install Node.js and npm (Node's package manager). Node is available cross-platform and you can download it from http://nodejs.org. Installing Node also installs npm. For this book, we are using Node.js version 8.9.4 and npm version 5.6.0. 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 and npm are installed, open a Command Prompt and type the following:

npm install -g @angular/cli

This installs the Angular CLI that we will use to start building our application. Now from a directory on your local machine, enter the following commands:

ng new guessthenumber --inlineTemplate
cd guessthenumber
ng serve

With the first command the Angular CLI will create a new Angular project on your local machine (the --inlineTemplate flag creates a template within our component, which is perfect for what we want to show in this chapter). With the second command, you are navigating to the directory that the Angular CLI has created for your new project. The third command launches the application, which you can view at http://localhost:4200/. If you do that you should see a standard default Angular page in the browser.

Installing Bootstrap

There is one more step before we build out the specifics of our application. Let’s add the Bootstrap library to enhance the look and feel of our application. First, stop the application by typing Ctrl + C in the Terminal from which it was launched and enter Y when asked if you want to terminate the batch job. Next from the guessthenumber directory, enter the following command:

npm install bootstrap --save

This will install the latest release of Bootstrap (which at the time of writing was version 4.0.0). You may see a few warning messages about unmet dependencies. You can ignore them.

Next configure your new project to include the Bootstrap style sheet:

  1. In the guessthenumber directory find and open the file angular.json
  2. In that file find the projects property, which contains the settings in our new project
  3. Then find the styles property within architect.build.options and you will see that it contains an array that holds styles.css, the default style sheet for our new project
  4. Add to that array the location of the bootstrap.min.css style sheet like so:
"styles": [
   "node_modules/bootstrap/dist/css/bootstrap.min.css",
   "src/styles.css"
],

Note

These instructions for including Bootstrap using the Angular CLI can be found at https://github.com/angular/angular-cli/wiki/stories-include-bootstrap.

What do we have so far?

If you take a look in the guessthenumber directory that the Angular CLI has been created, you will see a large number of files. This may look overwhelming at first, but the important thing to understand is that the Angular CLI has generated all these files for us withjust a few command line statements. In that way it makes getting started with an Angular application much smoother and easier. It takes the grunt work out of the process and enables us able to build and serve our application with minimal effort. In this chapter, we will be focusing on just a few files that we will need to touch in order to create our application.

Note

If you are running the application in Internet Explorer, there is one file that you will need to look at—polyfill.ts. This adds various other files that are needed to run the application in Internet Explorer. You will need to uncomment several sections in that file to add these necessary files. Instructions for doing this are contained in the file itself.

Before turning to building out the specifics of our application, let's take a look at one of the key files that will be used to get our application up and running.

Note

Downloading the example code

The code in this book is available on GitHub at https://github.com/chandermani/angular6byexample. 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/angular6byexample/tree/checkpoint1.1. Refer to the readme.md file in the guessthenumber folder when setting up the snapshot for the first time.

The host file - index.html

Navigate to the src folder in the guessthenumber directory and open index.html. You will see the following: 

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Guessthenumber</title>
  <base href="/">

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
  <app-root></app-root>
</body>
</html>

index.html is the host file for our application. It will be launched by the browser when the application is first run and will host the components in our application. If you have any exposure to web development, most of the HTML code in this file should look familiar . It has standard html, head, and body tags along with a couple of optional tags, one a meta tag for the viewport, which configures how the app will display in a mobile device, and the other a link to an Angular favicon image that will display on the tab in the browser in which the application is loaded.

Custom element

However, there is one more important tag on the page that may not look as familiar to you:

<app-root></app-root> 

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

Note

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

The component file

Now let's turn to building out the specifics of our application. Given the previous discussion of the component pattern, you will not be surprised that to do this we will be constructing a component.  In this case our application will be simple enough that we will need only one component (later in this book you will see the use of multiple components as we build more complex applications). The Angular CLI has already given us a start by generating a component file for us. Of course, that file does not contain any of the particulars of our application, so we will have to modify it. To do that navigate to the src folder in the app directory and open app.component.ts.

The import statement

At the top of the page, you will find 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. 

Note

The Angular documentation describes a barrel as:A way to roll up exports from several ES2015 modules into a single convenient ES2015 module. The barrel itself is an ES2015 module file that re-exports selected exports of other ES2015 modules. For more information about barrels, see https://angular.io/guide/glossary#barrel.

Decorator

Next, replace the code block that starts with @Component with the following:

@Component({
 selector: 'app-root',
 template: `
  <div class="container">
      <h2>Guess the Number !</h2>
        <div class="card bg-light mb-3">
           <div class="card-body">
              <p class="card-text">Guess the computer generated random number between 1 
                                                                          and 1000.</p>
           </div>
        </div>
       <div>
         <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>
      <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 it 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 <app-root> 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 replace the code block that begins with  export class AppComponent with the following:

export class AppComponent {
  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 AppComponent. 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 a 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 it 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 take a look at our Angular module file. Again the Angular CLI has created this file for us. Open app.module.ts in the app directory within the src folder and you will see the following:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

The first two statements import BrowserModule and NgModule. 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 AppComponent. If you go back to that component you will notice that export is added in front of the class definition, which means we are using module loading within our own application.

We next define a new component AppModule.  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. The first 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: AppComponent. 

We next 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 providers. This property is used to register providers (such as services and other objects) that will be available to be used throughout our application through dependency injection. We have no need for providers in the simple application we are building here, so this property is empty. We will be discussing providers and dependency injection in detail in Chapter 3, More Angular – SPA, Routing.

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

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

Bootstrapping

The class definition for AppComponent 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 src folder, look for a file named main.ts. Open it and you will see the following code:

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

if (environment.production) {
  enableProdMode();
}

platformBrowserDynamic().bootstrapModule(AppModule)
  .catch(err => console.log(err));

As you can see, we are importing enableProdMode from @angular/core and the platformBrowserDynamic module from @angular/platform-browser-dynamic. Like the import of BrowseModule in the appModule file, this latter import is specifically for browser-based applications. Next we add an import of our AppModule and a file called environment that is located in the environments directory of our application.

In the next lines of code we check to see if the constant environment in the environment file has its production property set to true, and if so, call enableProdMode(), which as the name suggests enables production mode. The default setting for environment.production is false, which is fine for our purposes here since we are not running the application in production mode.

Note

If you open environments.ts, you will see some comments that provide guidance for overwriting the settings in this file as part of the build process. We won't be covering the Angular build process until Chapter 2, Building Our First App – 7 Minute Workout; so we won't cover that material here.

Finally, we call the platformBrowserDynamic().boostrapModule method with our AppModule as a parameter. The bootstrapModule method then creates a new instance of our AppModule component, which in turn initializes our AppComponent, which we have marked as the component to bootstrap. It does that by calling our component's constructor method.

We're up and running!

Well, the app is complete and ready to be tested! From the guessthenumber directory again type the following:

ng serve

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/angular6byexample. 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/angular6byexample/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 and template, we should be mightily impressed with what we have achieved. 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 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 template in  app.component.ts:

<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 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
  • 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 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.

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 template in app.component.ts, 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 template in app.component.ts, 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 our 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 that we 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 ng-template, which is Angular's implementation of the Web Components template that we discussed earlier. 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 state


First, let's look at how we maintain 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 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:

 <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"&gt; 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, as follows:

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.

 

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:

 

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 now 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 some useful tools and resources that will help you get started with Angular development.

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

(9 reviews total)
very good book, very informative
It is impossible to read the book in epub format, because it is not displayed correctly in my ereader by the size of the letters, they look very large and I can not modify correctly the settings defined by the publisher. And in mobi format, it doesn't look right either. Although the size is the right one black strip scratches each I bought them to be able to read them anywhere with the benefits of these formats and I can only read them in pdf.
Un ottimo aiuto in campo sia professionale che personale.

Recommended For You

Book Title
Access this book and the full library for just $5/m.
Access now