Learning Angular
Learning Angular
Learning Angular
EPUB is an open, industry-standard format for e-books. However, support for EPUB
and its many features varies across reading devices and applications. Use your
device or app settings to customize the presentation to your liking. Settings that you
can customize often include font, font size, single or double column, landscape or
portrait mode, and figures that you can click or tap to enlarge. For additional
information about the settings and features on your reading device or app, visit the
device manufacturer’s Web site.
Second Edition
Brad Dayley
Brendan Dayley
Caleb Dayley
Learning Angular, Second Edition
Copyright © 2018 by Pearson Education, Inc.
All rights reserved. No part of this book shall be reproduced, stored in a retrieval
system, or transmitted by any means, electronic, mechanical, photocopying,
recording, or otherwise, without written permission from the publisher. No patent
liability is assumed with respect to the use of the information contained herein.
Although every precaution has been taken in the preparation of this book, the
publisher and author assume no responsibility for errors or omissions. Nor is any
liability assumed for damages resulting from the use of the information contained
herein.
ISBN-13: 978-0-134-57697-8
ISBN-10: 0-134-57697-7
1 17
Trademarks
All terms mentioned in this book that are known to be trademarks or service marks
have been appropriately capitalized. Pearson cannot attest to the accuracy of this
information. Use of a term in this book should not be regarded as affecting the
validity of any trademark or service mark.
Special Sales
For information about buying this title in bulk quantities, or for special sales
opportunities (which may include electronic versions; custom cover designs; and
content particular to your business, training goals, marketing focus, or branding
interests), please contact our corporate sales department at
[email protected] or (800) 382-3419.
For questions about sales outside the U.S., please contact [email protected].
Editor
Mark Taber
Managing Editor
Sandra Schroeder
Project Editor
Lori Lyons
Copy Editor
Kitty Wilson
Indexer
Erika Millen
Technical Editor
Jesse Smith
Project Manager
Dhayanidhi
Karunanidhi
Cover Designer
Chuti Prasertsith
Contents at a Glance
Introduction
1 Jumping into JavaScript
2 Jumping into TypeScript
3 Getting Started with Angular
4 Angular Components
5 Expressions
6 Data Binding
7 Built-in Directives
8 Custom Directives
9 Events and Change Detection
10 Implementing Angular Services in Web Applications
11 Creating Your Own Custom Angular Services
12 Having Fun with Angular
Index
Contents
Introduction
1 Jumping into JavaScript
Setting Up a JavaScript Development Environment
Defining Variables
Understanding JavaScript Data Types
Using Operators
Arithmetic Operators
Assignment Operators
Applying Comparison and Conditional Operators
Implementing Looping
while Loops
do/while Loops
for Loops
for/in Loops
Interrupting Loops
Creating Functions
Defining Functions
Passing Variables to Functions
Returning Values from Functions
Using Anonymous Functions
Understanding Variable Scope
Using JavaScript Objects
Using Object Syntax
Creating Custom Defined Objects
Using a Prototyping Object Pattern
Manipulating Strings
Combining Strings
Searching a String for a Substring
Replacing a Word in a String
Splitting a String into an Array
Working with Arrays
Combining Arrays
Iterating Through Arrays
Converting an Array into a String
Checking Whether an Array Contains an Item
Adding Items to and Removing Items from Arrays
Adding Error Handling
try/catch Blocks
Throwing Your Own Errors
Using finally
Summary
2 Jumping into TypeScript
Learning the Different Types
Understanding Interfaces
Implementing Classes
Class Inheritance
Implementing Modules
Understanding Functions
Summary
3 Getting Started with Angular
Why Angular?
Understanding Angular
Modules
Directives
Data Binding
Dependency Injection
Services
Separation of Responsibilities
Adding Angular to Your Environment
Using the Angular CLI
Generating Content with the CLI
Creating a Basic Angular Application
Creating Your First Angular App
Understanding and Using NgModule
Creating the Angular Bootstrapper
Summary
4 Angular Components
Component Configuration
Defining a Selector
Building a Template
Using Inline CSS and HTML in Angular Applications
Using Constructors
Using External Templates
Injecting Directives
Building a Nested Component with Dependency Injection
Passing in Data with Dependency Injection
Creating an Angular Application that Uses Inputs
Summary
5 Expressions
Using Expressions
Using Basic Expressions
Interacting with the Component Class in Expressions
Using TypeScript in Angular Expressions
Using Pipes
Using Built-in Pipes
Using Built-in Pipes
Building a Custom Pipe
Creating a Custom Pipe
Summary
6 Data Binding
Understanding Data Binding
Interpolation
Property Binding
Attribute Binding
Class Binding
Style Binding
Event Binding
Two-Way Binding
Summary
7 Built-in Directives
Understanding Directives
Using Built-in Directives
Components Directives
Structural Directives
Attribute Directives
Summary
8 Custom Directives
Creating a Custom Attribute Directive
Creating a Custom Directive with a Component
Summary
9 Events and Change Detection
Using Browser Events
Emitting Custom Events
Emitting a Custom Event to the Parent Component Hierarchy
Handling Custom Events with a Listener
Implementing Custom Events in Nested Components
Deleting Data in a Parent Component from a Child Component
Using Observables
Creating an Observable Object
Watching for Data Changes with Observables
Summary
10 Implementing Angular Services in Web Applications
Understanding Angular Services
Using the Built-in Services
Sending HTTP GET and PUT Requests with the http Service
Configuring the HTTP Request
Implementing the HTTP Response Callback Functions
Implementing a Simple JSON File and Using the http Service to Access It
Implementing a Simple Mock Server Using the http Service
Implementing a Simple Mock Server and Using the http Service to Update
Items on the Server
Changing Views with the router Service
Using routes in Angular
Implementing a Simple Router
Implementing a Router with a Navigation Bar
Implementing a Router with Parameters
Summary
11 Creating Your Own Custom Angular Services
Integrating Custom Services into Angular Applications
Adding an Angular Service to an Application
Implementing a Simple Application that Uses a Constant Data Service
Implementing a Data Transform Service
Implementing a Variable Data Service
Implementing a Service that Returns a Promise
Implementing a Shared Service
Summary
12 Having Fun with Angular
Implementing an Angular Application that Uses the Animation Service
Implementing an Angular Application that Zooms in on Images
Implementing an Angular Application that Enables Drag and Drop
Implementing a Star Rating Angular Component
Summary
Index
About the Authors
Brad Dayley is a senior software engineer with more than 20 years of experience
developing enterprise applications and web interfaces. He has used JavaScript and
jQuery for years and is the author of Node.JS, MongoDB, and Angular Web
Development, jQuery and JavaScript Phrasebook and Sams Teach Yourself
AngularJS, JavaScript, and jQuery All in One. He has designed and implemented a
wide array of applications and services, from application servers to complex web
applications.
— Brad Dayley
We Want to Hear from You!
As the reader of this book, you are our most important critic and commentator. We
value your opinion and want to know what we’re doing right, what we could do
better, what areas you’d like to see us publish in, and any other words of wisdom
you’re willing to pass our way.
You can email or write directly to let us know what you did or didn’t like about this
book—as well as what we can do to make our books stronger.
Please note that we cannot help you with technical problems related to the topic of
this book and that due to the high volume of mail we receive, we might not be able to
reply to every message.
When you write, please be sure to include this book’s title and author, as well as
your name and phone or email address.
Email: [email protected]
The Web Edition can be viewed on all types of computers and mobile devices with
any modern web browser that supports HTML5.
To get access to the Learning Angular Web Edition all you need to do is register this
book:
1. Go to www.informit.com/register
2. Sign in or create a new account.
3. Enter ISBN: 9780134576978
4. Answer the questions as proof of purchase.
5. The Web Edition will appear under the Digital Purchases tab on your Account
page. Click the Launch link to access the product.
Introduction
Welcome to Learning Angular. This book is designed to catapult you into the world
of using Angular to build highly interactive and well-structured web applications.
The book covers the basics of the Angular framework and how to use it to build
well-designed, reusable components for web applications. Angular is one of the most
exciting and innovative technologies emerging in the world of web development.
The typical readers of this book want to master Angular for the purpose of building
highly interactive web applications. Typical readers will also want to leverage the
innovative Model View Controller (MVC) approach of Angular to implement well-
designed and structured web pages and web applications. Overall, Angular provides
an easy-to-implement, fully integrated web development platform that enables you to
implement amazing Web 2.0 applications.
Using Angular technology enables you to build logic directly into your web page to
bind the data model for the client web application to back-end services and
databases. Angular also enables you to easily extend the capability of HTML so that
the UI design logic can be expressed easily in an HTML template file. Following are
just a few of the things you will learn while reading this book:
How to quickly build Angular templates with built-in directives that enhance
the user experience
How to bind UI elements to the data model so that when the model changes, the
UI changes and vice versa
How to bind mouse and keyboard events directly to the data model and back-
end functionality to provide robust user interactions
How to define your own custom Angular directives that extend the HTML
language
How to implement client-side services that can interact with the web server
How to build dynamic browser views that provide rich user interaction
How to create custom services that can easily be reused in other Angular
applications
How to implement rich UI components such as zoomable images and
expandable lists as custom Angular directives
What Is Angular?
Angular is a client-side JavaScript framework developed mostly by Google. The
entire ideology behind Angular is to provide a framework that makes it easy to
implement well-designed and well-structured web pages and applications using an
MVC or Model View View Model (MVVM) framework.
Angular provides all that functionality to handle user input in the browser,
manipulate data on the client side, and control how elements are displayed in the
browser view. Here are some of the benefits Angular provides:
Data binding: Angular has a very clean method for binding data to HTML
elements, using its powerful scope mechanism.
Extensibility: The Angular architecture enables you to easily extend almost
every aspect of the language to provide your own custom implementations.
Clean code: Angular forces you to write clean, logical code.
Reusable code: The combination of extensibility and clean code makes it very
easy to write reusable code in Angular. In fact, the language often forces you to
do so when you’re creating custom services.
Support: Google is investing a lot into this project, which gives it an advantage
where other similar initiatives have failed.
Compatibility: Angular is based on JavaScript and has a close relationship with
the JavaScript standard. That makes it easier to begin integrating Angular into
your environment and reuse pieces of your existing code within the structure of
the Angular framework.
Chapter 1, “Jumping into JavaScript,” provides a JavaScript primer, just in case you
are not familiar with JavaScript. This chapter also walks you through the process of
setting up a development environment. You should at least check out the first few
sections, even if you are familiar with JavaScript, so that you can create the
development environment.
Chapter 3, “Getting Started with Angular,” covers the basics of the Angular
framework. You will learn how Angular is organized and how to design Angular
applications.
Chapter 7, “Built-in Directives,” covers the directives that are built into Angular.
Directives allow you to change the structure of DOM elements as well as utilize
HTTP attributes.
Chapter 9, “Events and Change Detection,” covers the types of events you will
encounter in Angular and how to manage them. You will learn how to create and
handle your own custom events. This chapter also covers how to use observables to
watch for and react to data changes in your web applications.
Chapter 10, “Implementing Angular Services in Web Applications,” covers the built-
in services that Angular provides. These services enable you to communicate with
the web server using HTTP requests, implement routing to navigate application view
changes, and implement animations on web pages.
Chapter 11, “Creating Your Own Custom Angular Services,” covers the mechanics
available in Angular to create your own custom services. Custom services enable
you to make functionality reusable because you can easily inject the functionality
provided by these services into multiple applications.
Chapter 12, “Having Fun with Angular,” provides several examples of using
Angular to create rich UI components in real-world examples. You will get a chance
to see how to implement drag and drop, animations, and other UI elements.
Finally
Enjoy this book and enjoy learning about Angular. It is a great, innovative
technology that is really fun to use. Soon you’ll be able to join the many other web
developers who use Angular to build interactive websites and web applications.
1
Jumping into JavaScript
The first part of this chapter discusses the necessary basics of setting up a JavaScript
development environment. You should at least take a quick look at this section even
if you already are familiar with JavaScript and have a development environment set
up.
The rest of this chapter familiarizes you with some of the language basics of
JavaScript, such as variables, functions, and objects. It is not intended as a full
language guide but rather a synopsis of important syntax and idioms. If you are not
familiar with JavaScript, working through this primer should enable you to
understand the examples throughout the rest of the book. If you already know
JavaScript well, you can either skip those sections or review them as a refresher.
Defining Variables
You use variables in JavaScript to temporarily store and access data from your
JavaScript files. Variables can point to simple data types such as numbers or strings,
or they can point to more complex data types such as objects.
To define a variable in JavaScript, you use the var keyword and then give the
variable a name, as in this example:
var myData;
You can also assign a value to the variable in the same line. For example, the
following line of code creates a variable myString and assigns the value "Some
Text" to it:
After you have declared a variable, you can use its name to assign a value to the
variable and access the value of the variable. For example, the following code stores
a string in the myString variable and then uses it when assigning the value to the
newString variable:
You should give variables descriptive names so that you know later what data they
store and can more easily use them in your programs. A variable name must begin
with a letter, $, or _, and it cannot contain spaces. In addition, variable names are
case sensitive, so, for example, myString is different from MyString.
Number: This data type stores data as a numeric value. Numbers are useful in
counting, calculations, and comparisons. The following are examples:
var myInteger = 1;
var cost = 1.33;
Boolean: This data type stores a single bit that is either true or false.
Booleans are often used for flags. For example, you might set a variable to
false at the beginning of some code and then check it on completion to see if
the code execution hit a certain spot. The following examples define true and
false variables:
var yes = true;
var no = false;
Array: An indexed array is a series of separate distinct data items, all stored
under a single variable name. JavaScript arrays are heterogeneous, which means
they support different types of objects in the same array. Items in the array can
be accessed by their zero-based index, using array[index]. The following
is an example of creating a simple array and then accessing the first element,
which is at index 0:
Click here to view code image
Object literal: JavaScript supports the ability to create and use object literals.
When you use an object literal, you can access values and functions in the
object by using object.property syntax. The following example shows
how to create and access properties of an object literal:
Click here to view code image
Null: Sometimes you do not have a value to store in a variable either because it
hasn’t been created or you are no longer using it. At such a time, you can set a
variable to null. Using null is better than assigning a value of 0 or an empty
string ("") because those may be valid values for the variable. In addition,
null is better than undefined because it specifies that a value has been set.
By assigning null to a variable, you can assign no value and check against
null inside your code, like this:
var newVar = null;
Note
JavaScript is not a strongly typed language. That means you do not need to
specify in the script the data type of a variable. The interpreter automatically
figures out the correct data type for a variable. In addition, you can assign a
variable of one type to a value of a different type. For example, the following
code defines a string variable and then assigns it to an integer value type:
var id = "testID";
id = 1;
Using Operators
JavaScript operators allow you to alter the value of a variable. You are already
familiar with the = operator used to assign values to variables. JavaScript provides
several different operators that fall into two categories: arithmetic and assignment
operators.
Arithmetic Operators
You use arithmetic operators to perform operations between variable and direct
values. Table 1.1 lists the arithmetic operations, along with the results that are
applied.
+ Addition x=y+5 9
x=y+"5" "45"
x="Four"+y+"4" "Four44"
- Subtraction x=y-2 2
++ Increment x=y++ 4
x=++y 5
-- Decrement x=y-- 4
x=--y 3
* Multiplication x=y*4 16
/ Division x=10/y 2.5
Note
You can also use the + operator to add strings together or to add strings and
numbers together. It allows you to quickly concatenate strings as well as add
numeric data to output strings. Table 1.1 shows that when you add a numeric
value and a string value, the numeric value is converted to a string and then the
two strings are concatenated.
Assignment Operators
You use an assignment operator to assign a value to a variable. In addition to the =
operator, there are several different forms that allow you to manipulate the data as
you assign a value. Table 1.2 lists the assignment operations, along with the results
that are applied.
= x=5 x=5 5
+= x+=5 x=x+5 15
-= x-=5 x=x-5 5
*= x*=5 x=x*5 50
/= x/=5 x=x/5 2
%= x%=5 x=x%5 0
Comparison Operators
A comparison operator evaluates two pieces of data and returns true if the
evaluation is correct and false if the evaluation is not correct. A comparison
operator compares the value on the left of the operator against the value on the right.
Table 1.3 lists the comparison operators and provides some examples.
x==10 true
x==="10" false
!== Both value and type are not equal x!=="10" true
x!==10 false
You can chain together multiple comparisons by using logical operators and standard
parentheses. Table 1.4 lists the logical operators and shows how to use them to chain
together comparisons.
Table 1.4 JavaScript’s Comparison Operators, with Results Based on x=10 and
y=5 Initially
Operator Description Examples Result
!(x>y) false
Mix (x>=10 && y<x || x==y) true
Using if Statements
An if statement allows you to separate code execution based on the evaluation of a
comparison. The following lines of code show the conditional operators in () and
the code to execute if the conditional evaluates to true in {}:
if(x==5){
do_something();
}
In addition to only executing code within the if statement block, you can specify an
else block that will be executed only if the condition is false. Here is an
example:
if(x==5){
do_something();
} else {
do_something_else();
}
You can also chain together if statements. To do this, add a conditional statement
along with an else statement, as in this example:
if(x<5){
do_something();
} else if(x<10) {
do_something_else();
} else {
do_nothing();
}
Here is what happens: The switch statement evaluates the expression entirely and
gets a value. The value may be a string, a number, a Boolean, or even an object. The
switch expression is then compared to each value specified by the case
statement. If a value matches, the code in the case statement is executed. If no
values match, the default code is executed.
Note
Typically each case statement includes a break command at the end to signal a
break out of the switch statement. If no break is found, code execution
continues with the next case statement.
Implementing Looping
Looping is a means to execute the same segment of code multiple times. It is
extremely useful when you need to repeatedly perform the same tasks on an array or
a set of objects.
while Loops
The most basic type of looping in JavaScript is accomplished with the while loop.
A while loop tests an expression and continues to execute the code contained in its
{} brackets until the expression evaluates to false.
do/while Loops
Another type of while loop is the do/while loop, which is useful if you always
want to execute the code in the loop at least once and the expression cannot be tested
until the code has executed at least once.
For example, the following do/while loop executes until days is equal to
Wednesday:
The for statement uses the three statements as follows when executing the loop:
assignment: This is executed before the loop begins and not again. It is used
to initialize variables that will be used in the loop as conditionals.
condition: This expression is evaluated before each iteration of the loop. If
the expression evaluates to true, the loop is executed; otherwise, the for loop
execution ends.
update: This is executed on each iteration, after the code in the loop has
executed. This is typically used to increment a counter that is used in
condition.
The following example illustrates a for loop and the nesting of one loop inside
another:
Click here to view code image
for (var x=1; x<=3; x++){
for (var y=1; y<=3; y++){
console.log(x + " X " + y + " = " + (x*y));
}
}
Notice that the variable idx is adjusted each iteration through the loop, from the
beginning array index to the last. This is the resulting output:
It's Monday
It's Tuesday
It's Wednesday
It's Thursday
It's Friday
Interrupting Loops
When you work with loops, there are times when you need to interrupt the execution
of code inside the code itself, without waiting for the next iteration. There are two
different ways to do this: by using the break keyword and by using the continue
keyword.
The break keyword completely stops execution of a for or while loop. The
continue keyword, on the other hand, stops execution of the code inside the loop
and continues on with the next iteration. Consider the following examples.
Notice that the write is not executed for Wednesday because of the continue
statement, but the loop execution completes:
It's Monday
It's Tuesday
It's Thursday
It's Friday
Creating Functions
One of the most important parts of JavaScript is making code that other code can
reuse. To do this, you organize your code into functions that perform specific tasks.
A function is a series of code statements combined together in a single block and
given a name. You can execute the code in the block by referencing that name.
Defining Functions
You define a function by using the function keyword followed by a name that
describes the use of the function, a list of zero or more arguments in (), and a block
of one or more code statements in {}. For example, the following is a function
definition that writes "Hello World" to the console:
function myFunction(){
console.log("Hello World");
}
To execute the code in myFunction(), all you need to do is add the following line
to the main JavaScript or inside another function:
myFunction();
To call the greeting() function, you need to pass in a name value and a city
value. The value can be a direct value or a previously defined variable. To illustrate
this, the following code executes the greeting() function with a name variable
and a direct string for city:
var name = "Brad";
greeting(name, "Florence");
For example, the following code defines a function doCalc() that accepts three
parameters. The first two should be numbers, and the third is a function that will be
called and passed the two numbers as arguments:
Click here to view code image
function doCalc(num1, num2, calcFunction){
return calcFunction(num1, num2);
}
You could define a function and then pass the function name without parameters to
doCalc(), as in this example:
function addFunc(n1, n2){
return n1 + n2;
}
doCalc(5, 10, addFunc);
However, you also have the option of using an anonymous function directly in the
call to doCalc(), as shown in these two statements:
You can probably see that the advantage of using anonymous functions is that you
do not need a formal definition that will not be used anywhere else in your code.
Anonymous functions, therefore, make JavaScript code more concise and readable.
A function passed in as a parameter and called from inside is known as a callback
function. A big advantage of using a callback function is that the initial function does
not need to know anything about the function that will be executed, so you have
more flexibility.
JavaScript allows you to define both a global version and a local version of a
variable. The global version is defined in the main JavaScript, and local versions are
defined inside functions. When you define a local version in a function, a new
variable is created in memory. Within that function, you reference the local version.
Outside that function, you reference the global version.
To understand variable scoping a bit better, consider the code in Listing 1.1.
The global variable myVar is defined on line 1, and a local version is defined on line
3, within the writeIt() function. Line 4 writes "Variable = 2" to the
console. Then in line 5, writeMore() is called. Because there is no local version
of myVar defined in writeMore(), the value of the global myVar is written in
line 9.
To use a JavaScript object, you must first create an instance of the object. You create
object instances by using the new keyword with the object constructor name. For
example, to create a Number object, you could use the following line of code:
Object syntax is very straightforward: You use the object name and then a dot and
then the property or method name. For example, the following lines of code get and
set the name property of an object named myObj:
var s = myObj.name;
myObj.name = "New Name";
You can also get and set object methods of an object in the same manner. For
example, the following lines of code call the getName() method and then change
the method function on an object named myObj:
Click here to view code image
var name = myObj.getName();
myObj.getName = function() { return this.name; };
You can also create objects and assign variables and functions directly by using {}
syntax. For example, the following code defines a new object and assigns values and
a method function:
Click here to view code image
var obj = {
name: "My Object",
value: 7,
getValue: function() { return this.name; };
};
You can define JavaScript objects in a couple different ways. The simplest is the on-
the-fly method: Simply create a generic object and then add properties to it as
needed. For example, to create a user object and assign a first and last name as well
as define a function to return them, you could use the following code:
Click here to view code image
var user = new Object();
user.first="Brad";
user.last="Dayley";
user.getName = function( ) { return this.first + " " + this.last; }
You could also accomplish the same effect through direct assignment, using the
following code, where the object is enclosed in {} and the properties are defined
using property:value syntax. This method is referred to as object literal
notation:
These first two options work very well for simple objects that you do not need to
reuse later. A better method for reusable objects is to actually enclose an object
inside its own function block. This has the advantage of allowing you to keep all the
code pertaining to the object local to the object itself. Here is an example:
Click here to view code image
function User(first, last){
this.first = first;
this.last = last;
this.getName = function( ) { return this.first + " " + this.last;
};
var user = new User("Brad", "Dayley");
The end result of these methods is essentially the same as if you have an object with
properties that can be referenced using dot notation, as shown here:
console.log(user.getName());
Notice that you define the object UserP and then set UserP.prototype to
include the getFullName() function. You can include as many functions in the
prototype as you like. Each time a new object is created, those functions are
available.
Manipulating Strings
The String object is by far the most commonly used object in JavaScript.
JavaScript automatically creates a String object for you any time you define a
variable that has a string data type, as in this example:
Click here to view code image
var myStr = "Teach Yourself jQuery & JavaScript in 24 Hours";
When you create a string, there are a few special characters that you can’t add
directly to the string. For those characters, JavaScript provides a set of escape codes,
listed in Table 1.5.
To determine the length of a string, you can use the length property of the
String object, as in this example:
var numOfChars = myStr.length;
The String object has several functions that allow you to access and manipulate a
string in various ways. The methods for string manipulation are described in Table
1.6.
concat(str1, str2, ...) Joins two or more strings and returns a copy of
the joined strings.
fromCharCode() Converts Unicode values to actual characters.
slice(start, end) Returns a new string that has the portion of the
string between the start and end positions
removed.
To get you started on using the functionality provided in the String object, the
following sections describe some of the common tasks that can be done using
String object methods.
Combining Strings
You can combine multiple strings either by using a + operation or by using the
concat() function on the first string. For example, in the following code,
sentence1 and sentence2 will be the same:
Click here to view code image
var word1 = "Today ";
var word2 = "is ";
var word3 = "tomorrows\' ";
var word4 = "yesterday.";
var sentence1 = word1 + word2 + word3 + word4;
var sentence2 = word1.concat(word2, word3, word4);
The first method defines arr and sets the contents in a single statement, using [].
The second method creates the arr2 object and then adds items to it, using direct
index assignment. The third method creates the arr3 object and then uses the best
option for extending arrays: It uses the push() method to push items onto the
array.
To determine the number of elements in an array, you can use the length property
of the Array object, as in this example:
Arrays follow a zero-based index, meaning that the first item is at index 0 and so on.
For example, in the following code, the value of variable first will be Monday,
and the value of variable last will be Friday:
The Array object has several built-in functions that allow you to access and
manipulate arrays in various ways. Table 1.7 describes the methods attached to the
Array object that allow you to manipulate array contents.
concat(arr1, arr2, Returns a joined copy of the array and the arrays passed
...) as arguments.
pop() Removes the last element from the array and returns that
element.
push(item1, item2, Adds one or more new elements to the end of an array
...) and returns the new length.
slice(start, end) Returns the elements between the start and end
indexes.
To get you started using the functionality provided in the Array object, the
following sections describe some of the common tasks that can be done using
Array object methods.
Combining Arrays
You can combine arrays into a single array by using the concat() method but not
the + method. In the following code, the variable arr3 contains a string
representation of the elements in arr1 added to a string representation of the
elements in arr2. The variable arr4 in the following code is an array with the
combined elements from arr1 and arr2:
Click here to view code image
var arr1 = [1,2,3];
var arr2 = ["three", "four", "five"]
var arr3 = arr1 + arr2;
var arr4 = arr1.concat(arr2);
Note
You can combine an array of numbers and an array of strings. Each item in the
array will keep its own object type. However, as you use the items in the array,
you need to keep track of arrays that have more than one data type so that you do
not run into problems.
Table 1.8 Array Object Methods Used to Add and Remove Elements from
Arrays
Statement Value of x Value of arr
x = arr.pop(); 8 1,2,3,4,5,6,7
x = 4,5,6 1,2,3,four,five,six,7
arr.splice(3,3,"four",
"five","six");
try/catch Blocks
To prevent your code from totally bombing out, use try/catch blocks that can
handle problems inside the code. If JavaScript encounters an error when executing
code in a try block, it will jump down and execute the catch portion instead of
stopping the entire script. If no error occurs, the whole try block will be executed,
and none of the catch block will be executed.
For example, the following try/catch block tries to assign variable x to a value of
an undefined variable named badVarNam:
Notice that the catch statement accepts an err parameter, which is an error object.
The error object provides the message property, which provides a description of
the error. The error object also provides a name property that is the name of the
error type that was thrown.
The following is the console output, showing the different errors that are thrown,
based on input to the sqrRoot() function:
Can't Square Root Strings
Can't Square Root Nothing
sqrt(4) = 2
Sorry No Imagination
Using finally
Another valuable tool in exception handling is the finally keyword. You can add
this keyword to the end of a try/catch block. After the try/catch block is
executed, the finally block is always executed, whether an error occurs and is
caught or the try block is fully executed. This is especially useful in code that must
run no matter what happens in the try or catch blocks.
This chapter will familiarize you with the additions TypeScript gives to JavaScript.
If you are familiar with C# and object-oriented programming, TypeScript will seem
more familiar than JavaScript. This chapter will also familiarize you with the basics
of programming in TypeScript; it discusses types, interfaces, classes, modules,
functions, and generics. Like Chapter 1, “Jumping into JavaScript,” it is not intended
to be a full language guide; rather, it is a primer on the language to help prepare you
for using Angular.
Number: This data type stores data as a numeric value. Numbers are useful in
counting, calculations, and comparisons. Here are some examples:
var myInteger: number = 1;
var cost: number = 1.33;
Boolean: This data type stores a single bit that is either true or false.
Booleans are often used for flags. For example, you might set a variable to
false at the beginning of some code and then check it on completion to see if
the code execution hit a certain spot. The following examples define true and
false variables:
var yes: boolean = true;
var no: boolean = false;
Array: An indexed array is a series of separate distinct data items, all stored
under a single variable name. Items in the array can be accessed by their zero-
based index, using array[index]. The following are two examples of
creating a simple array and then accessing the first element, which is at index 0:
Click here to view code image
Null: Sometimes you do not have a value to store in a variable either because it
hasn’t been created or you are no longer using it. At such a time, you can set a
variable to null. Using null is better than assigning a value of 0 or an empty
string ("") because those may be valid values for the variable. By assigning
null to a variable, you can assign no value and check against null inside
your code, like this:
var newVar = null;
Any: In TypeScript you may not always know what type of variable you will be
getting or using. In such a case, you can assign the variable type as any to
allow any other type to be assigned to a variable. The following is an example
of assigning multiple types to the same variable:
Click here to view code image
Void: You use void when you don’t want a variable to have any type at all. In
TypeScript using void prohibits you from assigning or returning a value. In
most cases you use void when declaring a function you don’t want to have a
return value. The following example is a function of type void:
Click here to view code image
Enum: TypeScript lets us use enum, which allows you to give names to
enumerated values. The following is the syntax to declare enum:
Click here to view code image
or this:
var y = People[0]
By using this syntax, you set var x equal to the number 0 and var y equal to
the string Bob.
Understanding Interfaces
Interfaces are a fundamental part of TypeScript. They allow you to have a set
structure for an application. They are powerful tools that allow you to set structures
for objects, functions, arrays, and classes. You can think of interfaces as defining
standards you want your interface subsets to follow.
You can also add optional items to interfaces to allow some flexibility within a
program. You do this by using the syntax attribute?: Boolean;, as shown in
the following examples:
interface Person {
hairColor: string;
age: number;
alive?: Boolean;
}
You can define an interface for functions in TypeScript. This helps ensure that
functions take in specific types of parameters. The following example sets var z
equal to variables x + y, using an instance of the interface AddNums:
Interfaces also allow you to define how you would like arrays to look. You give
arrays the index type to define the types allowed for an object’s index. You then give
the return type for the index. Here is an example:
Click here to view code image
interface Stringy {
[index: number]: string;
}
var coolArray: Stringy;
coolArray = ["Apples", "Bananas"];
Finally, interfaces allow you to define class structures. As with a function interface,
this allows you to set required variables and methods within each class. It’s
important to note that this only describes the public portion of a class and not a
private section. (We talk more about classes in the next section.) In this example, the
interface has a property called name and a method called feed:
interface PersonInterface {
name: string;
feed();
}
Implementing Classes
JavaScript is a language that is based on prototype inheritance. Thanks to
ECMAScript 6 (ES6) and TypeScript, you can use class-based programming. You
can describe the objects you put into a program by using the base attributes to
describe classes.
To define a class in TypeScript, you use the syntax class ClassName{ code
goes here }. The following example defines a simple class that defines a
Person object with a feed function:
Notice that the last line uses the new keyword to call into the constructor and initiate
a new instance of the class with the name Brendan. This uses the constructor
method from the class, which pulls in "Brendan" and 21 as its parameters to
build a person named Brendan.
Say that you have a method feed as part of your class that you would like to be able
to use. Here is how you use it:
Brendan.feed()
Class Inheritance
Classes are subject to inheritance, and you can pass functionality to other classes by
using methods and attributes. This example shows how you can make an extension
of Person called SecretAgent and give it extra properties that Person doesn’t
have:
Click here to view code image
class SecretAgent extends Person {
licenseToKill: boolean = true;
weaponLoaded: boolean = true;
unloadWeapon() {
this.weaponLoaded = false;
return "clip empty";
}
loadWeapon() {
this.weaponLoaded = true;
return "locked 'n' loaded";
}
}
So now you have a class SecretAgent that extends the Person class. This
means you can still invoke the original feed method on the Person class, but it
gives you some extra attributes and methods on the SecretAgent class.
Implementing Modules
Modules in TypeScript allow you to organize your code over multiple files. This
helps keep your files shorter and more maintainable. Modules are able to do this by
allowing you to import the functionality you need from within the module you are
working on. You can do this if you export the class you need functionality from.
The following example splits the Person class into two separate modules:
In this example, the root module has the interface for Person. The submodule starts
by using /// <reference path="Person.ts" /> to point to the root
module so it can have access to the PersonInterface interface. The example
then proceeds to build the Person class in the submodule.
Understanding Functions
Functions in TypeScript are similar to functions in JavaScript, but they have added
capabilities. TypeScript functions allow you to give types to the parameters and even
to what will be returned by a function. While giving a function a type is optional, it’s
very helpful when you want to make sure that your functions don’t give you back
something you don’t want.
TypeScript allows you to give a function a return type, much in the same way you
give return types to variables. You first declare the function name and parameters,
and then you can define the type of the function. Also remember that you can assign
types to the parameters as well. Check out the following example:
Click here to view code image
function hello(x: string, y: string): string{
Return x + ' ' + y;
}
Like interfaces, TypeScript functions give you the power to create optional
parameters. This is helpful when you know that parameters may be circumstantial.
It’s important to know that optional parameters need to come after the required ones,
or an error will be thrown. The following example shows a function
soldierOfGondor which takes in a required variable name, and an optional
variable prefWeapon:
With TypeScript functions, you can create default parameters. A default parameter is
optional, but if it isn’t given, it has a default value instead of nothing. You create a
default parameter by setting one of the parameters equal to the desired default value:
Click here to view code image
function soldierOfGondor(name: string, prefWeapon = "Sword"){
return "hello " + name + " you can pick up your " + prefWeapon
+ " at the armory.";
}
Summary
Understanding TypeScript is critical to being able to use Angular to its full potential.
This chapter goes over enough of the fundamental TypeScript properties and
methods to get you through the rest of the book. You’ve learned how TypeScript
uses its different types and how to write and use interfaces, classes, modules, and
functions.
3
Getting Started with Angular
This chapter introduces you to Angular as well as the major components involved in
an Angular application. It is critical that you understand these components before
you try to implement an Angular application because the framework is different from
more traditional JavaScript web application programming.
After you get a good grasp of the components of an Angular application, you’ll learn
how to construct a basic Angular application, step by step. This should prepare you
to jump into the following chapters, which provide much more detail on
implementing Angular.
Why Angular?
JavaScript is a powerful programming language that allows developers to use a web
browser as a full application platform. Angular provides a great framework that
makes it faster and easier to create client-side JavaScript applications. Developers
use Angular because it provides a lot of the structure of web applications—such as
data binding, dependency injection, and HTTP communications—that teams would
otherwise need to develop themselves.
Understanding Angular
Angular is a JavaScript framework, which means it provides a number of APIs and
structure that helps you quickly and easily create complex client-side code. Angular
does a great job at providing not only features but also a basic framework and
programming model to create client applications. The following sections describe the
most important aspects of the Angular framework and how they contribute to make
Angular a great JavaScript framework.
Modules
In general, Angular apps use a modular design. While not required, modules are
highly recommended because they allow you to separate your code into separate
files. This helps you keep your code files short and manageable while still allowing
you to access the functionality from each one.
Unlike how you use modules with TypeScript, with Angular you import external
modules at the top of a file and export the functionality you need at the bottom. You
do this by using the key terms import and export, with the following syntax:
Directives
Directives are JavaScript classes with metadata that defines the structure and
behavior. Directives provide the majority of UI functionality for Angular
applications. There are three major types of directives:
Components: A component directive is a directive that incorporates an HTML
template with JavaScript functionality to create a self-contained UI element that
can be added to an Angular application as a custom HTML element.
Components are likely to be the directives you use the most in Angular.
Structural: You use structural directives when you need to manipulate the
DOM. Structural directives allow you to create and destroy elements and
components from a view.
Attribute: An attribute directive changes the appearance and behavior of
HTML elements by using HTML attributes.
Data Binding
One of the best features of Angular is the built-in data binding—the process of
linking data from a component with what is displayed in a web page. Angular
provides a very clean interface to link model data to elements in a web page.
When data is changed on a web page, the model is updated, and when data is
changed in the model, the web page is automatically updated. This way, the model is
always the only source for data represented to the user, and the view is just a
projection of the model.
Dependency Injection
Dependency injection is a process in which a component defines dependencies on
other components. When the code is initialized, the dependent component is made
available for access within the component. Angular applications make heavy use of
dependency injection.
A common use for dependency injection is consuming services. For example, if you
are defining a component that requires access to a web server via HTTP requests,
you can inject the HTTP services into the component, and the functionality is
available in the component code. In addition, one Angular component consumes the
functionality of another via dependency.
Services
Services are the major workhorses in the Angular environment. Services are
singleton classes that provide functionality for a web app. For example, a common
task of web applications is to perform AJAX requests to a web server. Angular
provides an HTTP service that houses all the functionality to access a web server.
Separation of Responsibilities
An extremely important part of designing Angular applications is the separation of
responsibilities. The whole reason you choose a structured framework is to ensure
that code is well implemented, easy to follow, maintainable, and testable. Angular
provides a very structured framework to work from, but you still need to ensure that
you implement Angular in the appropriate manner.
The following are a few rules to follow when implementing Angular:
The view acts as the official presentation structure for the application. Indicate
any presentation logic as directives in the HTML template of the view.
If you need to perform any DOM manipulation, do it in a built-in or custom
directive JavaScript code—and nowhere else.
Implement any reusable tasks as services and add them to your modules by
using dependency injection.
Ensure that the metadata reflects the current state of the model and is the single
source for data consumed by the view.
Define controllers within the module namespace and not globally to ensure that
your application can be packaged easily and avoid overwhelming the global
namespace.
Note
We recommend that you use Visual Studio Code (https://code.visualstudio.com/);
it has good TypeScript and Angular support built in, and is a light-weight editor
with many available extensions.
Fortunately, the Angular team has done most of the work for you here. All you need
to do is go to the Angular QuickStart website, which walks you through the process.
The following Angular QuickStart website takes you through the basics of Angular:
https://angular.io/docs/ts/latest/quickstart.html. This website explains the basics of
Angular’s command-line interface (CLI): https://angular.io/docs/ts/latest/cli-
quickstart.html.
Note
We recommend that you use the CLI while learning Angular. The CLI generates
all the bootstrap and configuration files for you. It also includes a lightweight
server for testing your code.
From the command line, run the command ng new [application name] to
create a new Angular application. If you navigate to that newly created application,
you have access too many other useful commands. Table 3.1 lists some of the most
important commands that the CLI has to offer.
While an in-depth guide of everything the CLI has to offer is beyond the scope of
this book, it is worth learning how to use.
For this example, it is expected that you have started working through the Angular
QuickStart guide and understand the basics of the CLI. The first thing to do is to
create a directory where you can place your projects.
When you have your directory set up, the next step is to generate your first Angular
application. Run the following command to create the application for this example:
ng new first
Next, run the following command to launch a server that will render the application:
ng serve
The following sections describe the important steps in implementing the Angular
application and the code involved in each step. Each of these steps is described in
much more detail in later chapters, so don't get bogged down in them here. What is
important at this point is that you understand the process of implementing the
HTML, component, class, and bootstrap and generally how they interact with each
other.
Figure 3.1 shows the web application you are going to create. It shows a simple
message that has been printed out by an Angular component.
Figure 3.1 Implementing a basic Angular web application that uses a component to
load an HTML template to the view
After the decorator is defined, lines 8–10 create the export class to make your
component available to the rest of the application as well as define variables and
functions that are made available to the component template.
As is often the case, it’s easiest to learn this by doing, so let’s get started using
NgModule. Navigate to the file named app.module.ts in your app folder. It
looks like this:
Click here to view code image
01 import { BrowserModule } from '@angular/platform-browser';
02 import { NgModule } from '@angular/core';
03 import { FormsModule } from '@angular/forms';
04 import { HttpModule } from '@angular/http';
05
06 import { Chap3Component } from './app.component';
07
08 @NgModule({
09 declarations: [
10 Chap3Component
11 ],
12 imports: [
13 BrowserModule,
14 FormsModule,
15 HttpModule
16 ],
17 providers: [],
18 bootstrap: [Chap3Component]
19 })
20 export class AppModule { }
Navigate to the file named main.ts in your app folder, which looks like this:
platformBrowserDynamic().bootstrapModule(AppModule);The
environment variable determines the state of the application—whether it should be
deployed in development mode or production mode.
Now open the command prompt, navigate to your root directory, and run the
command ng serve. This command compiles your code and opens a browser
window. You may need to point your browser to the local host and port. The
command lets you know the URL to navigate your browser to, as shown in the
following example:
Listing 3.1 shows the html index file that loads the application. Line 12 shows where
the message component gets applied.
Listing 3.2 shows the Angular module that bootstraps the component. Lines 1–4
show the Angular modules BrowserModule, NgModule, FormsModule, and
HttpModule each getting imported. Line 6 shows the Angular component
Chap3Component getting imported. Lines 9–11 show the component being
declared. Lines 12–16 show the imports array which makes the imported modules
available to the application. Line 18 bootstraps the main component of the
application.
Note
This application doesn’t need the FormsModule, or the HttpModule to run.
However, they are included to help show the syntax of importing extra modules
into the application.
Listing 3.3 shows the Angular component which has the selector message. This
component displays the message Hello World! In the browser.
Listing 3.1 first.html: A Simple Angular Template That Loads the First
Component
Click here to view code image
01 <!doctype html>
02 <html>
03 <head>
04 <meta charset="utf-8">
05 <title>First</title>
06 <base href="/">
07
08 <meta name="viewport" content="width=device-width, initial-
scale=1">
09 <link rel="icon" type="image/x-icon" href="favicon.ico">
10 </head>
11 <body>
12 <message>Loading...</message>
13 </body>
14 </html>
Listings 3.4 and 3.5 show the compiled JavaScript code from the TypeScript files in
Listings 3.2 and 3.3.
Note
This is the only time we show you the compiled JavaScript files in this book
because these are generated automatically for you when the application is
compiled and run—and to help keep the book more readable.
Summary
The Angular framework provides a very structured method for creating websites and
web applications. Angular structures a web application using a very clean,
componentized approach. Angular uses data binding to ensure that there is only one
source of data. It also takes advantage of templates with directives that extend
HTML capabilities, enabling you to implement totally customized HTML
components.
This chapter looks at the different components in an Angular application and how
they interact with each other. At the end of this chapter, a detailed example of how to
implement a basic Angular application, including a component, a module, and a
bootstrapper is seen.
4
Angular Components
Angular components are the building blocks you use to create Angular applications.
Angular components allow you to build self-contained UI elements for an
application. Components allow you to control how your application looks and
functions through TypeScript code and an HTML template. This chapter discusses
how to create Angular components using a TypeScript class that defines the look and
behavior of UI elements.
Component Configuration
An Angular component consists of two main parts: the definition in the decorator
section and the class section, which defines the logic. The decorator section is used
to configure the component, including things like the selector name and HTML
template. The class section allows you to give the component its logic, data, and
event handlers, as well as export it to be used in other TypeScript files.
With these two sections you can create a basic component. The following example
shows what a component might look like:
Click here to view code image
Import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: '<p>My Component</p>'
})
Export class AppComponent{
Title = 'Chapter 1 Example';
}
selector: This option allows you to define the HTML tag name used to add
the component to the application via HTML.
template: This option allows you to add inline HTML to define the look of
the component. This is for when there won’t be very much code to add, and it’s
helpful for when you don’t want extra files.
templateUrl: This option allows you to import an external template file
rather than inline HTML. This is helpful for separating a large amount of
HTML code out of a component to help with maintainability.
styles: This option allows you to add inline CSS to your component. Use it
when only minor style changes are needed.
stylesUrls: This option allows you to import an array of external CSS
stylesheet(s). You should use this rather than styles when importing external
CSS files.
viewProviders: This is an array of dependency injection providers. It
allows you to import and use Angular services that provide application
functionality such as HTTP communications.
Defining a Selector
In a component, a selector tells Angular where to apply the component in HTML.
You apply Angular a component to HTML by giving it a selector and then using the
selector name as a tag name in your HTML file. This makes the functionality of the
Angular component available in HTML. The following is an example of a selector:
Click here to view code image
@Component({
selector: 'angular-rules'
})
You can then add the selector to HTML files by using the following
syntax:
<angular-rules></angular-rules>
Note
It’s important to note that when defining a selector name, there can’t be any white
spaces. For example, you can’t name a selector angular rules, but you can
name it angular-rules or angular_rules.
Building a Template
You use a template to define how an Angular component should look. Templates are
written in HTML, but they allow you to include Angular magic to do some pretty
cool things. Angular allows for both inline templates and external template files.
You can add a template to the Angular @component decorator. For a single-line
template, you can use either single or double quotes to wrap it. For a multiple-line
template, you use backquotes (`); you generally find the backquote key in the upper
left of your keyboard, on the same key as the tilde symbol (~). Using the backquote
is very important as it will break your code if it’s not correct. Here is an example of a
single-line template compared to a multiple-line template:
Click here to view code image
@Component({
selector: 'my-app',
template: '<h1>Hello World!</h1>'
})
@Component({
selector: 'my-app',
template: `
<h1>Hello World!</h1>
`
})
Note
For the template and styles configuration options, you need to use the backquote
(`), generally located on the same key as the tilde symbol (~).
The same principles you use for templates also apply to CSS. You use the keyword
styles to tell a component about inline styling. The only major difference is that
styles takes in an object of strings instead of just one string. The following example
shows some inline styling:
Click here to view code image
@Component ({
selector: 'my-app',
template: '<p>hello world</p>',
styles: [`
P {
color: yellow;
font-size: 25px;
}
`]
})
Note
You need to use the backquote key for a multiple-line stylesheet.
In this exercise you will see how Angular components use and include external
templates and stylesheets. The purpose of this exercise is to illustrate how this use of
templates allows for more readable and manageable code.
The code in Listing 4.1 is the Angular component. Line 1 imports the component
necessary to define the component. Lines 3 through 18 define the component. The
component has a very simple template, as shown in lines 5 through 7, and some CSS
styling in lines 8 through 13 to go with it.
Using Constructors
When you use Angular, you often need to have default values and an initial setup for
your component variables. Angular uses constructors to give its components default
values. This section goes over how to create and implement them.
Constructors go in the Component class. Their purpose is to set default values and
initial configuration of variables for that class so that when those variables are used
within the component, they are never uninitialized. The following is an example of
constructor syntax:
export class constructor {
name: string;
constructor(){
this.name = "Brendan";
{
}
Now that you’ve learned what a constructor is and what it looks like, let’s get into an
example that uses one. This simple exercise uses a constructor to define the current
date at the time the component is created.
Listing 4.2 shows an Angular component with a selector named simple-
constructor and a simple template. Note the {{today}} on line 6 is a form of
data binding, which is discussed in more detail in Chapter 6, “Data Binding.” For
now, you should focus on how the constructor works.
You use the keyword styleUrls to tell the component about external stylesheets.
The difference with the external stylesheets is that you pass in an array of one or
more stylesheets. The following example shows how to import external stylesheets:
Click here to view code image
@Component ({
selector: 'my-app',
templateUrl: "./view.example.html"
styleUrls: ["./styles1.css", "./styles2.css"]
})
Note
The styleUrls configuration option takes in an array of comma-separated
strings.
Earlier in this chapter, in the “Building a Template” section, you learned how to
implement external HTML and CSS files into an Angular component. The example
in this section builds on that knowledge and walks you through an Angular
application that incorporates external HTML and CSS files.
Listing 4.3 shows an Angular component with the selector named external, and
templateUrl and styleUrls, which link the external files you need for this
application.
Injecting Directives
Dependency injection can be a difficult concept to fully grasp. However, it is a very
important part of Angular, and when you understand the basics, the Angular
implementation becomes quite clear. Dependency injection is a well-known design
pattern in many server-side languages but had not been used extensively in a
JavaScript framework until Angular came along.
Listing 4.8 shows the outer.css file this gives the outer component and its child
components default styles. These styles are inherited by the inner component.
Listing 4.9 shows the inner.component.ts file. This is the inner component
that the outer component has injected. Notice that the selector for this component,
which was used to load this directive within the outer component, is nested.
Listing 4.7 outer.html: An HTML Template for the Component to Apply the
View
Click here to view code image
01 <div>
02 <h1>the below text is a nested component</h1>
03 <nested></nested>
04 </div>
Listing 4.8 outer.css: A CSS Stylesheet for the Outer Component to Apply
to Its Template
Click here to view code image
01 div {
02 color: red;
03 border: 3px ridge red;
04 padding: 20px;
05 }
06 nested{
07 font-size: 2em;
08 font-weight: bolder;
09 border: 3px solid blue;
10 }
In Angular, to input data to another directive or component, you need to import the
Input decorator from @angular/core. The following code shows the syntax:
When the Input decorator has been imported, you can begin to define what data
you would like to have input into the directive. Start by defining @input(), which
takes in a string as a parameter. The HTML uses that string to pass in the data to the
imported directive. Do this by using the following syntax:
Click here to view code image
@Input('name') personName: string;
Creating an Angular Application that Uses Inputs
Now that you have learned how to use inputs with dependency injection, it’s time to
get started on an example. This section walks through an Angular application that
passes data to a directive from another directive.
Listing 4.10 shows the person.component.ts file, which is the entry point for
the application that will pass data into the input.component.ts file.
Listing 4.11 shows the input.component.ts file. It is the component that will
take in and handle the inputs from an external directive.
Summary
Angular components are the main building blocks of Angular applications. This
chapter shows how to build a component, from the decorator to the class. It shows
different ways of including templates and stylesheets. It also shows how to use
dependency injection to incorporate external directives or components within each
other.
5
Expressions
Using Expressions
Using expressions is the simplest way to represent data from a component in an
Angular view. Expressions are encapsulated blocks of code inside brackets, like this:
{{expression}}
The Angular compiler compiles an expression into HTML elements so that the
results of the expression are displayed. For example, look at the following
expressions:
{{1+5}}
{{'One' + 'Two'}}
Based on these expressions, the web page displays the following values:
6
OneTwo
Expressions are bound to the data model, which provides two huge benefits. First,
you can use the property names and functions that are defined in the component
inside your expressions. Second, because the expressions are bound to the
component, when data in the component changes, so do the expressions. For
example, say that a component contains the following values:
name: string='Brad';
score: number=95;
You can directly reference the name and score values in the template expressions,
as shown here:
Name: {name}}
Score: {{score}}
Adjusted: {{score+5}}
Because the Angular template expressions have access to the component, you can
also make changes to the component inside the Angular expression. For example,
this (click) directive changes the value of msg inside the component model:
The following sections take you through some examples of using the expression
capability in Angular.
Listing 5.1 shows an Angular component. This component has a template that
contains several types of expressions wrapped in double curly brackets ({{}}).
Some of the expressions are just numbers or strings, some include the + operation to
combine strings and/or numbers, and one applies a === operator to compare two
numbers.
Figure 5.1 shows the rendered web page. Note that numbers and strings are rendered
directly to the final view. Adding strings and numbers together enables you to build
text strings that are rendered to the view. Also note that using a comparison operator
renders the word true or false to the view.
Listing 5.2 shows an Angular component file that applies Angular expressions that
use values from the Component class to render text to the screen as well as act as
parameters to functions. Note that the variable names in the Component class can
be used directly in the expressions. For example, the expression in line 9 creates a
string based on the values of the speed and vehicle variables.
Figure 5.2 shows the rendered web page, based on the expressions. Note that when
the links of the page are clicked, the resulting function calls adjust the Component
class variables, which changes how the previously discussed expressions are
rendered.
Listing 5.3 implements an Angular component that uses Angular expressions that
take advantage of push() and shift()to display the arrays, show the array
length, and manipulate the array elements. Note that with Math added to the
Component class, you are able to use TypeScript Math operations directly in the
expressions in lines 12 and 21.
Figure 5.3 shows the Angular web page rendered. Notice that as the links are
clicked, the arrays are adjusted and the expressions are reevaluated.
Figure 5.2 Using Angular expressions to represent and use Component class data
in the Angular view
Using Pipes
A great feature of Angular is the capability to implement pipes. A pipe is a type of
operator that hooks into the expression parser and modifies the results of the
expression for display in a view—for example, to format time or currency values.
If you chain multiple pipes together, they are executed in the order in which you
specify them:
{{ expression | pipe | pipe }}
Some filters allow you to provide input in the form of function parameters. You add
these parameters by using the following syntax:
{{ {'name':'Brad'} | json }}
slice:start:end Limits the data represented in the expression by the
indexed amount. If the expression is a string, it is limited
in the number of characters. If the result of the expression
is an array, it is limited in the number of elements.
Consider these examples:
{{ ['a','b','c','d'] | slice:0:2 }}
{{ 123.4567 | number:1.2-3 }}
{{ 123.4567 | number:1.3 }}
{{1389323623006 | date:'yyyy-MM-dd
HH:mm:ss Z'}}
async Waits for a promise and returns the most recent value
received. It then updates the view.
Listing 5.4 shows the Angular component with a template that contains several
examples of built-in pipes wrapped in {{}} brackets. The Component class
contains data for some of the pipes to use.
Figure 5.4 shows the rendered application with the transformed data.
The @pipe decorator takes in metadata, just as an Angular component does. The
metadata options are name and pure. The name metadata works like the selector
of a component: It tells Angular where you want to use the pipe. The pure metadata
tells the pipe how to handle change detection. A pure pipe updates when there is a
change to the input value or an object reference. An impure pipe can update
whenever there is an event, such as a keystroke, mouse click, or mouse movement.
The following example demonstrates a sample pipe and its syntax:
@Pipe({
name: 'example',
Pure: true
})
The pipe class works much the same as the Component class, in that it is where
the logic of the pipe resides. However, the logic needs to be within a Transform
method, which tells the pipe how to transform whatever is to the left of the pipe
symbol (|). Review the following example:
Click here to view code image
Export class customPipe{
Transform(parameter1:string, parameter2:number) : string {
myStr = "logic goes in here";
return myStr;
}
}
Listing 5.5 shows an Angular pipe with the name metadata censor. The export
class contains the Transform method, which replaces certain words with a
different string and then returns the transformed string.
Listing 5.6 shows an Angular component which contains template that uses the
custom pipe, as well as the pipe metadata to import the pipe. Notice that on line 9,
there is the expression that you use to implement the pipe. The pipe takes in a string
as an argument and replaces the word with it.
Figure 5.5 shows the rendered application, using the custom pipe.
Summary
Angular comes with powerful built-in expressions and pipes and provides the option
to create custom pipes. This chapter discusses the available built-in expressions and
pipes and how to implement them. It also discusses how to build and implement a
custom pipe. Expressions are bits of typescript code contained within {{}}, and
pipes are able to manipulate those expressions. Expressions have access to
information within the Component class and can render class variables to the view.
6
Data Binding
One of the best features of Angular is the built-in data binding. Data binding is the
process of linking data from a component with what is displayed in a web page.
When data in the component changes, the UI rendered to the user is automatically
updated. Angular provides a very clean interface to link the model data to elements
in a web page.
There are many ways in Angular to use data binding to make an application look and
act in different ways. The following is a list of the types of data binding available
with Angular 2 that are discussed in this chapter:
Interpolation: You can use double curly braces ({{}}) to get values directly
from the Component class.
Property binding: You can use this type of binding to set the property of an
HTML element.
Event binding: You can use this type of binding to handle user inputs.
Attribute binding: This type of binding allows the setting of attributes to an
HTML element.
Class binding: You can use this type of binding to set CSS class names to the
element.
Style binding: You can use this type of binding to create inline CSS styles for
the element.
Two-way binding with ngModel: You can use this type of binding with data
entry forms to receive and display data.
Interpolation
Interpolation involves using the {{}} double curly braces to evaluate a template
expression. This can be in a hard-coded form, or it can reference a property of the
Component class.
The syntax for interpolation should look familiar from Chapter 5, “Expressions.”
However, you can also use interpolation to give an HTML tag property a value (for
example, the img tag). Here is an example of the syntax to do this:
<img src="{{imgUrl}}"/>
Now let’s look at an example that shows some cool things you can do with
interpolation binding.
Listing 6.1 shows an Angular component. This component has a template that
contains types of interpolation and expressions wrapped in {{}} brackets. The
Component class gives values to be used within the {{}} brackets. (Be sure to
change the imageSrc variable to the appropriate image name.)
Figure 6.1 shows the rendered web page. As you can see, interpolation can use
strings from the Component class to populate the template.
Property Binding
You use property binding when you need to set the property of an HTML element.
You do this by defining the value you want within the Component class. Then you
bind that value to the component template, using the following syntax:
<img [src]="myValue">
Note
In many cases, it is possible to use interpolation to achieve the same results you
get with property binding.
Note
In many cases, it is possible to use interpolation to achieve the same results you
get with property binding.
Now let’s take a look at an example of property binding. Listing 6.2 shows an
Angular component. This component has a template that contains types of property
binding. It also makes a comparison between property binding and interpolation.
Figure 6.2 shows the rendered web page. As you can see, interpolation can use
strings from the Component class to populate the template.
Figure 6.2 Using property binding to define an imageSrc URL, set a button to
disabled mode, and assign a class name
Attribute Binding
Attribute binding is similar to property binding but is tied to the HTML attribute
rather than the DOM property. You are not likely to use attribute binding very often,
but it is important to know what it is and how to use it. You will generally only use
attribute binding on attributes that do not have a corresponding DOM property (for
example, aria, svg, and table span attributes). You define an attribute binding
by using the following syntax:
Click here to view code image
<div [attr.aria-label] = "labelName"></div>
Note
Because attribute binding and property binding function almost the same way, we
do not present an example for attribute binding in this book.
Note
Because attribute binding and property binding function almost the same way, we
do not present an example for attribute binding in this book.
Class Binding
You use class binding to bind CSS style tags to HTML elements. It assigns the class
based on the result of an expression being true or false. If the result is true, the
class gets assigned. The following is an example of the syntax:
Click here to view code image
<div [class.nameHere] = "true"></div>
<div [class.anotherName] = "false"></div>
Now let’s take a look at an example of class binding. Listing 6.3 shows an Angular
component that has a template. This template contains types of class binding that
show how to apply a class name using two different methods.
Figure 6.3 shows the rendered web page. As you can see, the class names take effect
and allow the CSS styles to change the HTML.
Figure 6.3 An Angular application that applies class binding to add custom classes to
HTML elements
Style Binding
You use style binding to assign inline styles to an HTML element. Style binding
works by defining the CSS style property in the brackets, with the assignment
expression in the quotation marks. The syntax looks almost the same as for class
binding but with style instead of class as the prefix:
Click here to view code image
<p [style.styleProperty] = "assignment"></p>
<div [style.backgroundColor] = "'green'"></div>
Now let’s take a look at an example of style binding. Listing 6.4 shows an Angular
component that has a template. This template contains types of style binding that
show how to apply custom inline styles to an application.
Figure 6.4 shows the rendered web page. As you can see, the styles take effect, and
the CSS styles change the HTML accordingly.
Event Binding
You use event binding to handle user inputs such as clicking, keystrokes, and mouse
movements. Angular event binding is similar to HTML event attributes; the major
difference is that the prefix on is removed from the binding, and instead the event is
surrounded by parentheses (()). For example onkeyup in HTML looks like
(keyup) in Angular.
A common purpose for event binding is to run functions from the component. The
following is the syntax for click event binding:
Click here to view code image
<button (click)="myFunction()">button</button>
Let’s look at an example of event binding. Listing 6.5 shows an Angular component.
This component has event binding that calls a function to change the image URL
once clicked.
Figure 6.5 shows the rendered web page. You can see both the initial web page and
the results of clicking the button to trigger the event.
Figure 6.5 The initial result when the web page is loaded and the result from the
event being triggered
Two-Way Binding
Two-way binding allows for data to be easily displayed and updated simultaneously.
This makes it easy to reflect any changes the user makes to the DOM. Angular does
this by using ngModel to watch for changes and then update the value. This is the
syntax:
<input [(ngModel)] = "myValue">
Now let’s take a look at an example of two-way binding. Listing 6.6 shows an
Angular component that has a template. This template shows different ways to
accomplish two-way data binding.
Figure 6.6 shows the rendered web page. It shows that the styles take effect and the
CSS styles change the HTML accordingly.
Summary
Angular allows for powerful and very useful types of data binding. As you have seen
in this chapter, you can bind data in the application model to the UI elements that are
rendered to the user. This chapter goes over the available types of data binding and
how to implement them. Data binding allows for data to be both displayed to the user
and updated by the user in a simple and efficient manner.
7
Built-in Directives
One of the most powerful features Angular provides is directives. Directives extend
the behavior of HTML, enabling you to create custom HTML elements, attributes,
and classes with functionality specific to an application. Angular provides many
built-in directives, which provide the capability to interact with form elements, bind
data in a component to the view, and interact with browser events.
This chapter discusses the built-in directives and how to implement them in Angular
templates. You will learn how to apply these directives in your Angular templates
and support them in back-end controllers to quickly turn a rendered view into an
interactive application.
Understanding Directives
Directives are a combination of Angular template markup and supporting TypeScript
code. Angular directive markups can be HTML attributes, element names, or CSS
classes. The TypeScript directive code defines the template data and behavior of the
HTML elements.
The Angular compiler traverses the template DOM and compiles all directives. Then
it links the directives by combining a directive with a scope to produce a new live
view. The live view contains the DOM elements and functionality defined in the
directive.
The following sections describe these three types of directives. You do not need to
understand all the directives right away. The following sections provide tables for
reference. In addition, the following sections and chapters provide sample code for
using many of these directives.
Components Directives
Angular components are a form of structural directive that utilize a template. A
component creates a selector that is used as an HTML tag to dynamically add
HTML, CSS, and Angular logic to the DOM. Components are at the heart of
Angular.
Structural Directives
Several directives dynamically update, create, and remove elements from the DOM.
These directives create the layout, look, and feel of an application. Table 7.1 lists
these directives and describes the behavior and usage of each.
ngSwitchCase This directive evaluates the value it has stored against the
value passed into ngSwitch and determines whether the
HTML template it is attached to should be created.
ngSwitchDefault This directive creates the HTML template if all the above
ngSwitchCase expressions evaluate to false. This
ensures that some HTML is generated no matter what.
The directives in Table 7.1 are used in a variety of different ways in various parts of
the code. They allow for dynamic manipulation of the DOM, based on what data is
passed to them. Structural directives dynamically manipulate the DOM by using
expressions or values. Two of the most common structural directives are ngIf and
ngSwitch.
Note
ngFor is another example of a directive that uses the * symbol as a prefix to let
Angular know it’s there.
Listing 7.1 shows an Angular component which has a template that contains built-in
structural directives. The ngIf directive dynamically adds and removes HTML
from the DOM. ngSwitch does the same thing as ngIf, but it allows for more
options, along with a default option if all the cases return false.
Lines 6 and 7 in Listing 7.1 use ngIf to determine whether the HTML should be
displayed.
Line 10 shows the extended form of ngFor to dynamically add HTML based on the
amount of data passed to it. (This example simply shows another method of using
the ngFor directive, but the rest of the book will use the shorter form *ngFor.)
Line 15 uses the shorthand form of the ngFor directive to display data. This method
is used throughout the rest of this book.
Figure 7.1 shows the rendered web page. As you can see, interpolation can use
strings from the Component class to populate the template.
Listing 7.1 structural.component.ts: Structural Built-in Functions
Click here to view code image
01 import { Component } from '@angular/core';
02
03 @Component({
04 selector: 'app-root',
05 template: `
06 <div *ngIf="condition">condition met</div>
07 <div *ngIf="!condition">condition not met</div>
08 <button (click)="changeCondition()">Change
Condition</button>
09 <hr>
10 <template ngFor let-person [ngForOf]="people">
11 <div>name: {{person}}</div>
12 </template>
13 <hr>
14 <h3>Monsters and where they live</h3>
15 <ul *ngFor="let monster of monsters">
16 {{monster.name}}:
17 {{monster.location}}
18 </ul>
19 <hr>
20 <div [ngSwitch]="time">
21 <span *ngSwitchCase="'night'">It's night time
22 <button (click)="changeDay()">change to day</button>
23 </span>
24 <span *ngSwitchDefault>It's day time
25 <button (click)="changeNight()">change to night</button>
</span>
26 </div>
27 `
28 })
29 export class AppComponent {
30 condition: boolean = true;
31 changeCondition = function(){
32 this.condition = !this.condition;
33 }
34 changeDay = function(){
35 this.time = 'day';
36 }
37 changeNight = function(){
38 this.time = 'night'
39 }
40 people: string[] = [
41 "Andrew", "Dillon", "Philipe", "Susan"
42 ]
43 monsters = [
44 { name: "Nessie",
45 location: "Loch Ness, Scotland" },
46 { name: "Bigfoot",
47 location: "Pacific Northwest, USA" },
48 { name: "Godzilla",
49 location: "Tokyo, sometimes New York" }
50 ]
51 time: string = 'night';
52 }
Figure 7.1 Using built-in structural directives
Attribute Directives
Angular attribute directives modify how HTML elements look and behave. They are
injected straight into the HTML and dynamically modify how the user interacts with
an HTML segment. Attribute directives are so named because they often look like
normal HTML attributes. An example of an attribute directive that you’ve been
using throughout the book is ngModel, which modifies an element by changing the
display value.
Table 7.2 lists the attribute directives and describes the behavior and usage of each.
Directive Description
ngModel This directive watches a variable for changes and then updates display
values based on those changes. Consider these examples:
Click here to view code image
<input [(ngModel)]="text"><br>
<h1>{{text}}</h1>
ngForm This directive creates a form group and allows it to track the values and
validation within that form group. By using ngSubmit, you can pass the
form data as an object to the submission event. Here is an example:
Click here to view code image
<form #formName="ngForm" (ngSubmit)="onSubmit(formName)">
</form>
The directives in Table 7.2 are used in a variety of different ways in various parts of
the code. They allow for manipulation of an application’s behavior. The following
example shows how to use some of the built-in attribute directives to build a form
that submits data to a simulated database.
Listing 7.2 shows an Angular component. Lines 9 through 14 set the default values
for the variables used throughout the application. Lines 15 through 17 define the
enabler method, which sets the Boolean isDisabled to the opposite value of what
it was. Lines 18 through 30 define the addClass method, which pushes a value
from the event target to the selectedClass array.
Listing 7.3 shows an Angular template file that uses ngModel, ngClass,
ngStyle, and ngForm to modify the look and behavior of the HTML template.
Lines 7 through 12 create an HTML selection element that assigns a color to the
color variable on the attribute component. Lines 14 through 18 create an HTML
selection element that uses the change event to invoke the addClass method and
pass in the event object. Lines 16 through 21 display the output of the component
variables, using the ngClass and ngStyle directives to dynamically modify the
look of the elements.
The code in Listing 7.4 is the CSS for the component that sets up the styles for the
application.
Figure 7.2 shows the rendered web page. It shows that interpolation can use strings
from the Component class to populate the template.
Summary
Angular offers many built-in directives that provide functionality to manipulate the
look, feel, and behavior of an application, without requiring you to write large
amounts of code. This chapter goes over some of the available built-in directives and
provides examples of how to utilize Angular’s built-in directives.
8
Custom Directives
As with many other features of Angular, you can extend functionality by creating
your own custom directives. Custom directives allow you to extend the functionality
of HTML by implementing the behavior of elements yourself. If you have code that
needs to manipulate the DOM, it should be done inside a custom directive.
You implement a custom directive by calling the @directive class, much the
same way you define a component. The @directive class metadata should
include the selector of the directive to be used in the HTML. The Directive
export class is where the logic for the directive will reside. For example, the
following is a basic definition for a directive:
Click here to view code image
import { Directive } from '@angular/core';
@Directive({
selector: '[myDirective]'
})
export class myDirective { }
This section shows how to implement a custom attribute directive. The zoom
directive created in this example is designed to add custom functionality to whatever
image it is applied to. With this directive applied, you can scroll over an image with
the mouse wheel to make the element grow or shrink in size.
Listing 8.1 shows the zoom component, which displays a list of images. These
images have the zoom directive applied to them, allowing the mouse scroll event to
increase or decrease the size of each image.
Listing 8.2 shows the zoom directive. This directive has the selector zoom. This
directive imports Directive, ElementRef, HostListener, Input, and
Renderer from @angular/core to provide the functionality this directive
needs.
Lines 10 through 12 of Listing 8.2 watch for the mouse cursor to enter the element,
and when it does, it applies a border to the element with the border() function to
let the user know the directive is active.
Lines 14 through 16 remove the border when the cursor leaves the element to tell the
user the directive is no longer active.
Lines 17 through 26 listen for the mouse wheel to be activated. Depending on which
direction the wheel is scrolled, the element’s size is adjusted with the
changeSize() function.
Lines 27 through 31 define the border() function. This function takes in three
parameters and then applies those parameters to style the host element.
Lines 32 through 36 define the changeSize() function, which changes the size of
the host element.
Listing 8.3 shows the HTML file for zoom.component.ts. It creates a row of
images and applies the zoom directive to those images.
Listing 8.4 shows the styles for zoom.component.ts. It sets the height of the
images to 200px initially so they aren’t rendered huge if they have a high resolution.
The web page that results from Listings 8.1–8.4 is shown in Figure 8.1.
Listing 8.4 app.component.css: A CSS File that Sets the Image Height
Click here to view code image
01 img {
02 height: 200px;
03 }
Figure 8.1 Applying a custom attribute directive
The example in this section shows how to use a component as a custom directive to
change how the element looks with a containing template.
This example implements a custom directive container that is designed to add a
surrounding “container” HTML template to the element it is being applied to. This
directive has two inputs title and a description that can be used to give the host
element a description and title.
Listing 8.5 shows the root component, which displays various HTML elements.
These elements have the container directive applied, which adds a header with an
optional title, a footer with an optional description, and borders to each element.
Listing 8.6 shows the HTML for the root component. The code creates several
elements of different types, such as image, div, and p, and applies the container
directive to them.
Listing 8.7 shows the CSS for the root component. It sets a max image height to
keep the size of the image smaller. It also sets some default styling for the class diver
so that it is visible to the user.
Listing 8.8 shows the container directive. This directive has the selector
container and the inputs title and description. This directive imports
Directive, Input, and Output from @angular/core to provide the
functionality this directive needs. Note that in line 10, ng-content is used to tell
the component where to inject the external HTML. Lines 6 through 8 display the
passed-in title. Lines 12 through 14 display the description.
Listing 8.9 shows the HTML for the container directive. Lines 2 through 4 create the
title bar for the container. Lines 5 through 7 apply the content attribute directive.
ng-content acts as a placeholder and will be replaced with the template from the
container component shown in Listing 8.8. Lines 8 through 10 create the description
bar for the container component.
Listing 8.10 shows the CSS for the container component. This file sets the CSS to
give the container component borders, a title bar, and a description bar.
The web page that results from Listings 8.5 through 8.10 is shown in Figure 8.2.
Summary
Angular directives extend the behavior of HTML. Directives can be applied to
Angular templates as HTML elements, attributes, and classes. The functionality of
directives is defined in the @directive class. Angular provides several built-in
directives that interact with form elements, bind data, and interact with browser
events. For example ngModel binds the value of a form element directly to the
component. When the component value changes, so does the value displayed by the
element and vice versa.
One of the most powerful features of Angular is the ability to create your own
custom directives. Implementing a custom directive in code is simple, using the
@directive class. However, directives can also be very complex because of the
myriad ways they can be implemented.
9
Events and Change Detection
Angular has powerful browser events that extend HTML events by using Angular
data binding to handle responses. Some of the built-in Angular events are discussed
in Chapter 6, “Data Binding,” in the section “Event Binding.” This chapter goes over
built-in events, custom events, and event handling with an Angular application.
Table 9.1 lists some of the HTML events, along with their Angular counterparts and
short descriptions.
Table 9.1 HTML Events with Angular Syntax and a Description of the Event
HTML Event Angular Description
Syntax
onchange (change) Event that is fired when the value of the HTML
element is changed
onfocus (focus) Event that is fired when the HTML element is
selectedx
onkeypress (keypress)
onmouseover (mouseover) Event that is fired when the cursor moves over an
HTML element
Some of these events should be familiar to you as they have been used in previous
chapters. Notice that the Angular syntax uses one-way data binding, which involves
using () around each event to pass information about the event to the component.
Listing 9.1 shows a custom event component that uses a custom event from a child
component to pass data to a variable in the parent. Lines 9 through 11 implement a
custom event handler, which takes in an event and applies it to the variable text.
Listing 9.4 shows a component that creates a list of characters that can be
manipulated via custom events. The selectCharacter() function on line 21 is
an event handler that changes the character value, which can then be passed
down to the details component.
In Listing 9.7, line 10 creates the character input, which takes data in from the
parent. Line 11 creates the CharacterDeleted EventEmitter, which is used
on line 14 to pass the character data back up to the parent to be handled.
In Listing 9.8, line 8 invokes the deleteChar() method which then activates the
EventEmitter on line 41 to send the character data back to the parent
component.
Using Observables
Observables offer components a way to observe data that changes asynchronously,
such as data coming from a server or from user input. Basically, observables allow
you to watch values for changes over time. Unlike a JavaScript promise, which
returns a single value, an observable is capable of returning an array of values. This
array of values doesn’t have to be received all at once either, which makes
observables that much more powerful.
The subscription to the observable occurs in lines 7 through 11. This subscription
has three callback functions. the first is called when data is successfully received by
the subscription. The second is the error handler, which is called when the
subscription fails. The third is the final one, which runs code when the subscription
completes, whether the subscription succeeds or fails.
Listing 9.10 shows the component for the application. This component creates two
Observable objects, pass and run. These observables have a function that goes
and gets a random number between 0 and 30 and gives each number to one of the
two teams randomly until the combined total of both teams equals 1,000 or greater.
In Listing 9.10, lines 11 and 12 declare the observables pass and run. These
Observable objects are both initialized and subscribed to within the ngOnInit
function, which runs when the component is initialized.
The observable pass is initialized on lines 18 through 20, and run is initialized on
lines 27 through 28. Once they are initialized, pass and run both use the function
playLoop on lines 43 through 52. playLoop creates and sends an object that
contains a random number between 0 and 1 to determine the team and a random
number between 0 and 29 for yards. Each observable then interprets the team and
applies the yards to either the team’s pass yards or running yards.
Lines 57 through 59 create a random number generator that the rest of the
application uses to create the random numbers for the timeout functions, teams, and
yards.
Listing 9.11 shows the HTML for this example. This listing has three main parts.
Lines 3 through 5 show data for an imaginary team’s distance, in yards. Lines 8
through 10 show the same for a second team. Line 11 shows the combination of both
teams’ distances.
Summary
The capability to manage events is one of the most critical components in most
Angular applications. You can use events in Angular applications to provide user
interaction with elements as well as components of the application that communicate
with each other so they know when to perform certain tasks.
Components are organized into hierarchies, and the root component is defined at the
application level. In this chapter, you have learned how to emit events from within a
component and then implement handlers that listen for those events and get executed
when they are triggered. You have also learned about observables and how to
implement them for asynchronous watching of values.
10
Implementing Angular Services in Web
Applications
This chapter introduces built-in Angular services. You will get a chance to see and
implement some of the built-in services, such as http for web server
communication, router for managing and changing the state of an application, and
animate to provide animation capabilities.
Table 10.1 describes some of the most common built-in services to give you an idea
of what is available. The following sections cover the http and router services in
more detail.
animate Provides animation hooks to link into both CSS- and JavaScript-based
animations
router Provides navigation between views and between sections within views
forms Provides a service that allows for dynamic and reactive forms with simple
form validation
There are two ways to use the http service. The simplest is to use one of the
following built-in shortcut methods that correspond to standard HTTP requests:
delete(url, [options])
get(url, [options])
head(url, [options])
post(url, data, [options])
put(url, data, [options])
patch(url, data, [options])
In these methods, the url parameter is the URL of the web request. The optional
options parameter is a JavaScript object that specifies the options to use when
implementing the request. Table 10.2 lists some the properties you can set in the
options parameter.
Table 10.2 Properties that Can Be Defined in the config Parameter for http
Service Requests
Property Description
headers Headers to send with the request. You can specify an object
containing the header names to be sent as properties. If a
property in the object has a null value, the header is not sent.
The following is a simple example of a GET request that returns an observable with
syntax to add operators:
Click here to view code image
get(): Observable<any>{
http.get(url)
.map(response => response.JSON())
.catch(err => Rx.Observable.of('the error was: ${err}'));
}
Implementing a Simple JSON File and Using the http
Service to Access It
The code in Listings 10.1 through 10.5 implements a simple mock web server in the
form of a JSON file and the Angular application that accesses it. Figure 10.1 shows
the output. The web server contains a simple JSON object with a list of users. The
web application allows a user to view the list of users. The example is very
rudimentary to ensure that the code is easy to follow; it incorporates a GET request
as well as an error-handling example.
Listing 10.1 shows the JSON file that contains the JSON object. This file can be
accessed using an HTTP GET request, which allows http to grab the JSON object
and return it to the Angular application as an observable.
Listing 10.1 dummyDB.JSON: A JSON Object that Contains Data for Users
Click here to view code image
01 [
02 {
03 "userId": 1,
04 "userName": "brendan",
05 "userEmail": "[email protected]"
06 },
07 {
08 "userId": 2,
09 "userName": "brad",
10 "userEmail": "[email protected]"
11 },
12 {
13 "userId": 3,
14 "userName": "caleb",
15 "userEmail": "[email protected]"
16 },
17 {
18 "userId": 4,
19 "userName": "john",
20 "userEmail": "[email protected]"
21 },
22 {
23 "userId": 5,
24 "userName": "doe",
25 "userEmail": "[email protected]"
26 }
27 ]
Listing 10.2 implements the Angular component. http is imported on line 3, and
rxjs is imported on line 5. (Note that you may need to install rxjs via npm.) rxjs
allows toPromise() to be called on the observable object. Notice that the
constructor() method instantiates http on line 15. Line 16 shows an HTTP
GET request, which has the path to the dummyDB.JSON file passed in as url. The
toPromise() method is called to convert the observable response from the
http.get() method into a promise object. Once the promise completes,
.then() is called, which takes in the promise object data and applies it to the
array users so it can be displayed in the application. If an error occurs, catch is
called, which passes the error response object to a callback function to be used.
Listing 10.3 implements an Angular module that imports HttpModule to allow the
http service to be used throughout the application. HttpModule is imported from
@angular/http on line 4 and then added to the imports array on line 15.
Listing 10.4 implements an Angular template that uses ngFor to create a list of
users to be displayed in the application.
Listing 10.5 is a CSS file that styles the application so that each user is
distinguishable from the rest and easy to see.
This service is intended for development purposes only and shouldn’t ever be
used in a production application.
Listing 10.6 is the mock data service that returns the JSON object. This file will be
accessed using HTTP requests, which will allow http to modify the database. Line
1 imports InMemoryDbService, which allows Angular to use this as a database
where data can be stored while the session is active. The database is created and
made useable on line 3, using the createDb() method, which returns the users as
a JSON object.
Lines 39 through 52 define the createUser() function. This function takes two
parameters, username and email. It assigns those parameters to a user object
on lines 41 through 44. Lines 48 through 51 call the createUser() method on
the UserService and pass in the user object. Once the response is received, the
createUser() method pushes the response into the users array, which is
reflected immediately in the DOM.
Listing 10.8 implements the Angular service UserService, which handles all
theHTTP requests for the application. Lines 16 through 21 define the
deleteUser() method, which takes in the parameter id. An HTTP delete
request is then created using id to go to the server and delete the user with the
matching ID. Lines 22 through 31 define the createUser() method, which takes
in a user object. A post request passes the user to the server as a JSON string,
which is then added to the server.
Listing 10.9 implements an Angular template that utilizes ngFor to create a list of
users to be displayed within the application.
Listing 10.10 is a CSS file that styles the application so that each user is
distinguishable from the rest and easy to see.
Listing 10.12 is the mock data service that returns the JSON object. This file will be
accessed using HTTP requests, which will allow http to modify the database. Line
1 imports InMemoryDbService, which allows Angular to use this as a database
where data can be stored while the session is active. The database is created and
made usable on line 3, using the createDb() method, which returns the users as a
JSON object.
Listing 10.14 implements the Angular service UserService, which handles all the
HTTP requests for the application. Lines 16 through 24 define the updateUser
method, which takes in the parameter user. A URL is then generated to specify
which user will be updated. An HTTP put request is made on line 20, taking in the
generated URL and the user object, which is passed into the json.stringify
method. the updateUser method then sends a response object on success or
moves to the error handler on fail.
Listing 10.15 implements an Angular template that uses ngFor to create a list of
users to be displayed within the application. These users are each selectable. When
one is selected, the information is shown in an editable form field that allows the
user to be edited and saved. Lines 20 through 24 show the button that can be clicked
to invoke the updateUser method and pass in an object with that user’s updated
information.
Listing 10.15 update.component.html: An Angular Template that Displays
a List of Users and Can Be Updated
Click here to view code image
01 <h1>
02 Users
03 </h1>
04 <div class="userCard" *ngFor="let user of users"
05 (click)="selectUser(user)"
06 [class.selected]="user === selectedUser">
07 <div><span>Id:</span> {{user.id}}</div>
08 <div><span>Username:</span> {{user.userName}}</div>
09 <div><span>Email:</span> {{user.email}}</div>
10 </div>
11
12 <div *ngIf="selectedUser">
13 <label>user name:</label>
14 <input #updateName [ngModel]="selectedUser.userName"/>
15
16 <label>user email:</label>
17 <input #updateEmail [ngModel]="selectedUser.email" />
18
19
20 <button (click)="updateUser(
21 {'id': selectedUser.id,
22 'userName': updateName.value,
23 'email': updateEmail.value});
24 ">
25 Save
26 </button>
27 </div>
Listing 10.16 is a CSS file that styles the application so that each user is
distinguishable from the rest and easy to see. It provides some logic to help the user
know that each user can be clicked on.
To set up an app for routing, you need to import the Routes and Router modules
from @angular/router. To help keep the application simple to maintain,
router should get its own module that can be imported into the main application
module.
Many more parameters can be added to the route object. Table 10.3 shows a list of
some of them.
Table 10.3 Properties that Can Be Defined in the config Parameter for
route Service Object
Property Description
Once the routes array is defined, it needs to be implemented into the router so that
the router service knows it exists and knows how to use it. This is done by using
the forRoot method on RouterModule. The result of this is included in the
routing module’s imports array. The syntax for this looks as follows:
There are two ways to navigate between routes. The first way is from HTML
directly, using the Angular directive routerLink, which has the following syntax:
<a routerLink="/myRoute">
The second way to navigate between routes is from the component class, using the
following syntax:
Click here to view code image
myFunction(){
this.router.navigate(['myRoute'])
}
When the router is all wired up and ready to be used, the last step is to make sure the
routes get displayed on the application. You do this by using the Angular HTML tag
router-outlet. It is important to note that the component that uses router-
outlet will be outside the router, and anything besides router-outlet will
always display, no matter what route is currently being shown. You can implement
router-outlet by using the following syntax:
<router-outlet></router-outlet>
Listing 10.18 shows the Router module, which defines the routes for the
application. The Router module imports Routes and RouterModule to enable
routing within the application. The Router module also imports any components
that will be used as routes. Lines 5 through 14 define the routes array, which
contains the route definitions for the application. Lines 6 through 9 define the home
route that the application will default to because the path is set to an empty string.
The home route uses HomeComponent as the component that controls the view.
Lines 10 through 13 define a second route object that will be displayed when the
path is set to route2. This route uses Route2Component.
Listing 10.19 shows the root component for the application. This component has a
simple template that outputs router-outlet for router to display its routes.
Listing 10.20 shows the home component template file. This file displays a message
that lets the user know that the route is working, followed by a link that uses
routerLink to navigate the user to a separate view.
Listing 10.21 shows the home component file. This file is as barebones as a
component gets. Its main purpose is to load the template file and make it available to
the router.
Listing 10.22 shows the route2 component template file. This file displays a
message that lets the user know the route is working, followed by a link that uses
routerLink to navigate the user to a separate view.
Listing 10.23 shows the barebones route2 component file. Its main purpose is to
load the template file and make it available to the router.
Listing 10.24 shows the Router module, which defines the routes for the
application. The Router module imports any components that will be used as
routes. There isn’t a home route for this example. If the route is empty, the router
redirects to page1, as shown in lines 22 through 25. In addition, if an invalid route
is typed into the URL, the router again redirects to page1, as shown in lines 27
through 30.
Listing 10.25 shows the nav component, which controls the nav bar and links to the
views within the page. Lines 9 through 19 show an array of available pages which
the nav bar can use to create buttons with links for navigation.
Listing 10.26 shows the nav component template file. It creates a list of buttons that
allow for navigation between the named routes.
Listing 10.27 shows the nav component CSS file. This file styles the nav bar buttons
so they make sense. Lines 9 through 12 cause the color of the buttons and text to
change when the user hovers the mouse over a button.
Listing 10.28 shows the root component file app.component.ts, which serves
as the entry to the application and loads the routed views and the nav component.
Listing 10.29 shows the root component template file, which loads the nav
component followed by the router outlet, which is where the views are loaded for the
application.
Listing 10.30 shows the root component CSS file, which provides some spacing for
the nav bar so it is displayed nicely.
Listing 10.31 shows the page1 component. This component loads a template that
will be used as one of the views for this application. Line 5 loads an image to be
displayed on the view.
Listing 10.32 shows the page2 component. This component loads a template that
will be used as one of the views for this application.
Listing 10.33 shows the page2 template file, which contains some dummy text that
will be loaded into the view.
Listing 10.34 shows the page3 component. This component loads a template that
will be used as one of the views for this application.
Listing 10.35 shows the page3 template file, which creates a text area box to be
displayed on the view.
Listing 10.36 shows the Router module, which defines the routes for the
application. The Router module imports any components that will be used as
routes. Line 14 defines the path to page 2, which takes in the parameter
this.text.
Listing 10.37 shows the root component app.component.ts. This file has a
template that declares router-outlet to display the views from the router.
Listing 10.38 shows the page1 component. This component imports Router and
ActivatedRoute from @angular/router to allow this component to access
the router and read or assign parameters to RouterState. Lines 10 through 13
define the constructor, which on lines 11 and 12 implements ActivatedRoute
and Router as private variables route and router. Lines 14 through 22 define
the function gotoPage2(), which navigates to page2, passing in a parameter.
Line 16 navigates to page2, passing in this.text as the parameter. Lines 18 and
19 allow the application to change views without changing the URL in the browser.
Listing 10.39 shows the page1 template file. Line 4 shows a text area that is bound
to the variable text that is passed as a parameter when routed to page 2. Line 5
creates a button that invokes the gotoPage2 function, changing the view. This
button is available only when the variable text has a non-empty value.
Listing 10.40 shows the page2 component. This component imports Router and
ActivatedRoute from @angular/router to allow this component to access
the router and parameters that were set when the route was loaded. Lines 15 and 16
create a subscription to the params observable and assign the value to the variable
text to be displayed in the view.
Listing 10.41 shows the page2template file. Line 2 displays the variable text,
which gets its value from the route params. Line 3 creates a button that can be
clicked to navigate back to page 1.
Summary
Angular services are objects that contain functionality you can inject into other
Angular components. Angular’s built-in services provide a lot of prebuilt
functionality needed for your client code. For example, the http service allows you
to easily integrate web server communication into your Angular applications, and the
router service allows you to manage navigation between views.
11
Creating Your Own Custom Angular
Services
Angular provides a lot of functionality in its built-in services, but it also allows you
to implement your own custom services to provide specific functionality. You should
implement a custom service any time you need to provide task-based functionality to
an application.
When implementing custom services, you need to think about each service as being
a chunk of reusable code that performs one or more related tasks. Then you can
design and group them together into libraries that can easily be consumed by several
different Angular applications.
Mock service Provides dummy data that can be used to test HTTP-based
services while the back end is unavailable
Constant data Returns data variables that need to remain constant, such as
the mathematical value of pi
Variable data Returns data variables that can be changed, with the changed
value being saved to the service for other services to use
@Component({
selector: 'app-root',
template: '',
providers: [ CustomService ]
})
The final step in making a custom service usable is to create an instance of that
service to be used throughout the component. You do this in the constructor of the
component, as shown in the following example:
Click here to view code image
constructor(
private myService: CustomService
){}
When these steps are complete, the custom service and any of its methods are made
available to the component through the instance myService.
Listing 11.1 shows the pi service, which returns the value of pi. Lines 1 and 3
import and implement Injectable to make the service available to be used
externally. Line 4 creates the PiService class, which holds the definition for the
service. Lines 5 through 7 define the getPi method, which returns the value of pi.
Listing 11.1 pi.service.ts: Creating a Service that Returns the Value of Pi
Click here to view code image
01 import { Injectable } from '@angular/core';
02
03 @Injectable()
04 export class PiService {
05 getPi(){
06 return Math.PI;
07 }
08 }
Listing 11.3 shows an Angular template that displays the value of pi to five places.
Listing 11.3 app.component.html: An Angular Template That Displays the
Value of Pi to Five Places
Click here to view code image
01 <h1>
02 Welcome. this app returns the value of pi
03 </h1>
04 <p> the value of pi is: {{pi | number:'1.1-5'}}</p>
Listing 11.5 shows an Angular component that gets areas of shapes from
AreaCalcService, based on the values received from the user. Lines 2 and 8
import AreaCalcService and add it to the providers to make it available to the
component. Line 21 creates an instance of AreaCalcService as areaCalc to
be used with the component methods.
Lines 23 through 25 define the doCircle method, which implements the circle
method on areaCalc to get the area of a circle.
Lines 26 through 28 define the doSquare method, which implements the square
method on areaCalc to get the area of a square.
Listing 11.6 shows an Angular template file that creates form fields to input data
required to calculate the areas of various shapes. When the data is input, the area is
immediately calculated and displayed to the user.
Listing 11.7 shows a CSS file that styles the application, separating the individual
forms for each shape.
Figure 11.2 shows the resulting Angular application web page. As values are added
to the component, the areas are automatically calculated by the custom service.
Figure 11.2 An Angular application that uses a custom service to automatically
calculate the areas of different shapes
Listing 11.9 shows an Angular component that gets a random image from
RandomImageService, displays it in the main view, and adds it into the
imageHistory array. Lines 4 and 10 show RandomImageService being
imported and provided to the component. Line 17 instantiates the
RandomImageService as the variable randomImages. Lines 19 through 23
create a default initial imageInfo object to hold a place until data can be received
from RandomImageService. Lines 25 through 32 show the ngOnInit method,
which calls the getRandomImage method on the randomImages service
instance and assigns it to the observable randomImage. imageInfo is then
assigned the value of anything emitted from the observable. imageHistory also
adds the value of anything emitted from the observable.
Listing 11.10 shows an Angular template that displays a random image in the main
view. ngFor is used to display each image within the image history array.
Listing 11.11 shows a CSS file that styles the application with a border for the main
image and text.
Figure 11.3 shows the running example. The main image URL and size are randomly
changed by the service. A rolling history of the randomly displayed images is shown
at the bottom.
Figure 11.3 Implementing a variable data service that updates a component with
random changes to image size and URL
Listing 11.14 shows an Angular template that has an input the user can use to type
the amount of time in seconds. The template has a button that invokes the function
createAlert.
Figure 11.4 shows the asynchronous alert being displayed by the service after the
time has elapsed.
Figure 11.4 Using an Angular service to provide asynchronous alerts
Lines15 through 52 define the characters array, which contains the values
name, race, alignment, and health. Lines 55 through 60 define the
constructor method, which creates the observable charObservable. The
observer object is saved to the service variable observer. Then the observer emits
the characters array. Lines 62 through 64 define the getCharacters method,
which returns the charObservable.
Listing 11.17 shows an Angular template that displays two sections: one for good
guys one for bad guys. Line 2 shows the Good Guys component, which takes in an
input shared and is passed the shared observable from app.component to
good-guys.component. Line 5 shows the Bad Guys component, which takes
in an input shared and is passed the shared observable from app.component
to badguys.component.
Listing 11.19 shows an Angular template that displays a list of characters. Lines 3
through 5 display the character’s name, race, and health. Lines 6 through 8 show that
characters with the alignment 'bad' have a button that invokes the
hitCharacter method which takes in the character object and the number
25 as parameters.
Listing 11.20 shows a CSS file that adds borders to each character to help distinguish
the characters as separate entities.
Listing 11.22 shows an Angular template that displays a list of characters. Lines 3
through 5 display the character’s name, race, and health. Lines 6 through 8 show that
characters with the alignment 'good' also have a button that invokes the
hitCharacter method to which takes in the character object and 25 as
parameters.
Listing 11.23 shows a CSS file that adds borders to each character to help distinguish
the character as separate entities.
Figure 11.5 shows the application that connects a Good Guys component with a
Bad Guys component. Clicking the hit button updates the shared service, which is
observed by both components.
Figure 11.5 Using a shared Angular service to update multiple components
Summary
Angular custom services provide functionality that can be injected into other
Angular services and components. Services allow you to organize your code into
functional modules that can be used to create libraries of functionality available to
Angular applications.
This chapter focuses on tools that enable you to implement your own custom
Angular services for providing task-based functionality to applications. This chapter
provides examples of implementing each of various types of custom Angular
services.
12
Having Fun with Angular
Listing 12.1 shows the application module. For the application to use the animation
service, BrowserAnimationsModule needs to be loaded. Lines 3 and 15 show
BrowserAnimationsModule being imported from @angular/platform-
browser/animations and then added to the imports array to make
animations available to the application.
Listing 12.2 shows an Angular component that acts as the root of the application.
This component loads a template file that uses the animated component.
Listing 12.3 shows an Angular template that loads the animated component four
times and passes in an image URL to the input src. It also adds a title to the input
title.
Listing 12.4 shows an Angular animated component which handles the animation
of an image that is passed in via an input. Lines 1 through 3 import animate,
keyframes, state, style, transition, and trigger from
@angular/core to make animations for this application possible.
Lines 9 through 36 define the animations metadata for the component. Lines 10
through 23 show the trigger for the animation called fadeState, which when
activated calls two states, inactive and active, and two transitions,
inactive => active (which creates a 500 ms ease-in animation) and
active => inactive (which creates a 500 ms ease-out animation).
Lines 24 through 34 show the trigger bounceState, which contains the transition
void => *. This transition creates an animation that causes the menu items to
bounce down and up when the application is first loaded. Lines 45 through 47 define
the enter method, which sets the variable state to active. Lines 48 and 49
define the leave method, which sets the variable state to inactive.
Listing 12.5 shows an Angular template that displays a title and an image. Line 1
shows the Angular animation @bounceState being used; it is passed in the
variable state from the component to determine what animation sequence should
be used. Lines 7 and 8 show @fadeState being implemented; it also has state
passed in to determine the animation sequence.
Listing 12.6 shows a CSS file that styles the titles for the images and sets the
dimensions for the images.
Figure 12.1 shows how the images animate in size and opacity when you click on the
image name.
Figure 12.1 Using Angular“s built-in animation service to animate images
Listing 12.7 shows an Angular component that acts as the root of the application.
This component loads a template file that uses the zoomit component.
Listing 12.8 shows an Angular template that creates three zoomit components by
passing in the image URL as the attribute zsrc.
Listing 12.9 shows the Angular zoomit component, which handles zooming in on a
section of an image by using browser events. Lines 13 through 16 define the
ngOnInit method, which generates a URL to get an image based on the name of
the image passed into the component via the zsrc input. ngOnInit then sets a
default position. Lines 18 through 23 define the imageClick event, which takes in
a parameter event. Then it gets the element from the event object and uses that to
set new x and y coordinates as the basis for the zoom of the image.
Listing 12.10 shows an Angular template that displays an image and a zoomed in
portion of the image next to it, using the coordinates generated from the
imageClick function.
Listing 12.11 shows a CSS file that styles the application by adding a border to the
zoomed in image. It also sets width and height to 100px.
Listing 12.11 zoomit.component.css: A CSS File That Styles the
Application
Click here to view code image
01 img {
02 width: 200px;
03 }
04 .zoombox {
05 display: inline-block;
06 border: 3px ridge black;
07 width: 100px;
08 height: 100px;
09 background-repeat: no-repeat;
10 }
Figure 12.2 shows how the custom component displays a zoomed in portion of the
image. When you click on the image, the position of the zoom is changed.
Figure 12.2 Implementing a custom Angular component that zooms in on a portion
of an image
Listing 12.12 shows an Angular component that implements the drag-item and
drop-item components to apply tags to images. Lines 12 through 24 define the
constructor, which initializes a list of tags available to be dragged onto an image.
Listing 12.13 shows an Angular template that implements the drag-item and
drop-item components, which allow tags to be dragged and dropped onto images.
Listing 12.14 shows a CSS file that styles the application to give direct styles to the
drop-item custom HTML tag.
Listing 12.15 shows the Angular component drop-item, which uses browser
events to allow an element to be dropped onto the component element. Lines 11
through 13 define the constructor that initializes the tags variable as an empty
array.
Lines 16 through 18 define the allowDrop method, which takes an event object
as a parameter. The preventDefault method is invoked on the event object.
Lines 19 through 25 define the onDrop method, which takes in an event object as
a parameter. preventDefault is called on the event object. Then the variable
data is assigned tagData from the event to allow Angular to add that data to the
tags array and to the list on the image.
Listing 12.16 shows an Angular template that displays an image and any tags
assigned to that image.
Listing 12.18 shows the Angular component drag-item, which uses browser
events to allow elements to be dragged. Lines 14 through 17 define the onDrag
method, which takes an event object as a parameter. This method adds data to the
dataTransfer item on the event object to allow the tag data to be transferred
when the element is dropped.
Listing 12.20 shows a CSS file that styles the application by adding custom styles to
the tags.
Figure 12.3 shows how the drag-item and drop-item components work in a
browser: When you drag a tag onto an image, the tag is added to the list below.
Figure 12.3 Implementing drag and drop using Angular components
Listing 12.22 shows an Angular service that acts as a mock database for the
application. Lines 4 through 29 create an array of items that can be retrieved and
updated via HTTP requests.
Listing 12.23 shows an Angular service that uses HTTP to retrieve and update the
items in the mock database. Lines 6 through 11 define the RatedItem interface
with strictly typed variable names. Lines 19 through 24 define the constructor that
creates an instance of http and a new observable called itemObservable.
Once a response is received from the observable, the getItems method is called.
Lines 27 and 28 define the getObservable method, which returns
itemObservable. Lines 30 through 38 define the getItems method, which
uses an HTTP get to retrieve the items list from the mock database; it then assigns
the items variable to the response and emits that response to the observer.
Listing 12.24 shows an Angular component that handles getting the items from
RatingsService. Lines 21 through 27 define ngOnInit, which invokes the
getObservable method on ratingsService to assign the items observable
to itemsObservable. The items variable is then assigned the response
received from itemsObservable.
Listing 12.26 shows a CSS file that styles the item class on
app.component.html.
Listing 12.27 shows an Angular component that displays a rated item. Lines 13
through 15 define the constructor method, which initializes the starArray
value.
Lines 18 through 20 define the setRating method, which takes the parameter
rating. The method invokes the updateRating method on the ratings
service and takes the parameters item and rating, which the ratings service uses
to update the rating of the item.
Lines 21 through 27 define the getStarClass method, which takes the parameter
rating. This method is used to assign the class of each star to accurately represent
the rating of the item.
Listing 12.28 shows an Angular template that displays a title, an image, and a rating.
Lines 8 through 12 create the stars, which are used to visualize the rating. When a
user clicks on a new rating, the overall rating is adjusted, using the setRating
method. The getStarClass method determines whether the stars are filled in or
blank.
Listing 12.29 shows a CSS file that styles the application by setting the dimensions
of the rated item and adding stars to give that item a visualized rating.
Figure 12.4 shows the star rating component in the browser. Clicking on a star
changes the rating in the mock back-end service, which updates the UI component.
Figure 12.4 Using Angular components and services to implement star ratings on
images with a mock back end
Summary
In this chapter, you got a chance to see how to extend what you have learned in the
rest of the book to build some cool Angular components. You have seen how to
implement animations, create a star rating component, and implement drag-and-drop
capability. These are just some of the many ways to use Angular in real-world web
applications. If you are interested in learning more about angular https://angular.io is
a great resource.
Index
Symbols
+ (addition) operator, 8
&& (and) operator, 10
= assignment operator, 9
/= assignment operator, 9
+= assignment operator, 9
–= assignment operator, 9
%= assignment operator, 9
*= assignment operator, 9
` (backquotes), 50–51
{ } (curly braces), 10, 14, 61, 62, 75
-- (decrement) operator, 8
/ (division) operator, 8
== (equal) operator, 9
=== (equal) operator, 9
\' escape code, 20
\" escape code, 20
\\ escape code, 20
> (greater than) operator9
>= (greater than or equal to) operator, 9
++ (increment) operator, 8
< (less than) operator, 9
<= (less than or equal to) operator, 9
% (modulo) operator, 8
* (multiplication) operator, 8
!= (not equal) operator, 9
!== (not equal) operator, 9
! (not) operator, 10
|| (or) operator, 10
( ) (parentheses), 10, 14, 82, 103
| (pipe symbol), 72
- (subtraction) operator, 8
~ (tilde), 50–51
A
ActivatedRoute, importing, 134
addClass() method, 92
addition operator, 8
AddNums interface, 31
alerts, asynchronous, 162
allowDrop() method, 182
and operator, 10
Angular bootstrapper, creating, 44–48
app.module.js, 47
app.module.ts, 46
first.component.js, 48
first.component.ts, 46
first.html, 45
Angular QuickStart website, 40
animate service, 116
animated component
animated.component.css, 175
animated.component.html, 175
animated.component.ts, 173–174
animation application
animated.component.css, 175
animated.component.html, 175
animated.component.ts, 173–174
app.component.html, 172–173
app.component.ts, 172
app.module.ts, 171–172
folder structure, 171
anonymous functions, 16
any data type, 30
app.component.css listing
AreaCalcService, 155
custom directive with component, 100
drag-and-drop application, 181–182
RandomImageService, 159
router with navigation bar, 141
star rating application, 190
app.component.html listing
animation application, 172–173
AreaCalcService, 154–155
custom directive with component, 99–100
drag-and-drop application, 181
image zoom application, 177
PiService, 152
PromiseService, 162
RandomImageService, 159
router with navigation bar, 140
SharedService, 165
star rating application, 189–190
zoom directive, 97–98
app.component.ts listing
animation application, 172
AreaCalcService, 153–154
custom directive with component, 99
drag-and-drop application, 180–181
image zoom application, 176–177
PiService, 151
PromiseService, 161–162
RandomImageService, 158–159
router with navigation bar, 140
router with parameters, 144
SharedService, 165
simple router application, 135–136
star rating application, 189
app.module.js listing, 47
app.module.ts listing
Angular bootstrapper, 46
animation application, 171–172
simple mock server implementation, 119–120, 126
simple router implementation, 134–135
star rating application, 186
AppRoutingModule, importing, 134
app-routing.module.ts listing
router with navigation bar, 138–139
router with parameters, 144
simple router implementation, 135–136
AreaCalcService, 152–156
app.component.css, 155
app.component.html, 154–155
app.component.ts, 153–154
area-calc.service.ts, 152–153
area-calc.service.ts listing, 152–153
arithmetic operators, 8
Array object, 22–25
adding items to, 25
combining, 24
converting into strings, 24
iterating through, 24
manipulating, 22–24
methods, 23
removing items from, 25
searching, 25
arrays
JavaScript, 7
adding items to, 25
combining, 24
converting into strings, 24
iterating through, 24
manipulating, 22–24
methods, 23
removing items from, 25
searching, 25
routes, defining, 132–133
TypeScript, 30
assignment operators, 8–9
asterisk (*), 8
async pipe, 70
asynchronous alerts, 162
attribute binding, 79
attribute directives, 38, 91–94
attribute.component.css, 94
attribute.component.html, 93
attribute.component.ts, 92–93
custom attribute directives, 95–98
ngForm, 91
ngModel, 91
ngStyle, 91
attribute.component.css listing, 94
attribute.component.html listing, 93
attribute.component.ts listing, 92–93
B
\b (backspace) escape code, 20
backquotes (`), 50–51
backspace escape code, 20
Bad Guys component
badguys.component.css, 168
badguys.component.html, 168
badguys.component.ts, 167
basicExpressions.component.ts listing, 63
binding. See data binding
Boolean data type
JavaScript, 7
TypeScript, 29
bootstrap metadata option (NgModule), 43
bootstrapper, creating, 44–48
app.module.js, 47
app.module.ts, 46
first.component.js, 48
first.component.ts, 46
first.html listing, 45
border() function, 96
brackets ({ }), 61, 62
break statement, 13–14
browser events, 103–104
BrowserAnimationsModule, loading, 172
browsers
browser events, 103–104
support for, 5–6
building templates, 50–51
built-in directives, 87–88
attribute directives, 38, 91–94
attribute.component.css, 94
attribute.component.html, 93
attribute.component.ts, 92–93
ngForm, 91
ngModel, 91
ngStyle, 91
components directives, 38, 88
structural directives, 38, 88–91
definition of, 87
ngFor, 88, 120, 125, 130, 159
ngIf, 88–89
ngSwitch, 88–89
ngSwitchCase, 88, 89
ngSwitchDefault, 88
structural.component.ts, 89–90
built-in events, 103–104
built-in pipes
builtInPipes.component.ts, 71–72
table of, 69–70
built-in services
animate, 116
forms, 116
http, 116
GET requests, sending, 116–117
JSON file implementation and access, 118–121
PUT requests, sending, 116–117
request configuration, 117
response callback functions, 117
simple mock server implementation, 121–127
simple mock server updates, 127–132
router, 116
ActivatedRoute, importing, 134
route navigation, 134
route object parameters, 133
Router, importing, 134
router with navigation bar, 138–143
router with parameters, 143–147
routes array, 132–133
routing module, including, 134
simple router implementation, 134–137
builtInPipes.component.ts listing, 71–72
C
callback functions, 16
canActivate property (route object), 133
canActivateChild property (route object), 133
canDeactivate property (route object), 133
canLoad property (route object), 133
carriage return escape code, 20
Cascading Style Sheets. See CSS (Cascading Style Sheets)
catch() method, 117
catch statement, 26
change detection, 111–114
(change) event, 103
changeLoop() method, 156
changeSize() function, 96
character.component.css listing, 108
character.component.html listing, 108
character.component.ts listing, 107–108
charAt() method, 20
charCodeAt() method, 20
charObservable, 163
child components, deleting parent data from, 107–110
Children property (route object), 133
class binding, 79–80
class.component.ts listing, 80
classes. See also services
@directive, 95
binding, 79–80
Component, 64–66
defining, 32
EventEmitter, 104
export classes
Directive, 95
ZoomDirective, 97
inheritance, 33
pipe, 72
SecretAgent, 33
classExpressions.component.ts listing, 64–65
CLI (command-line interface), 40–41. See also commands
(click) event, 103
code listings. See listings
combining
arrays, 24
strings, 21
command-line interface. See CLI (command-line interface)
commands. See also directives
ng eject, 41
ng generate component, 41
ng generate directive, 41
ng generate enum, 41
ng generate guard, 41
ng generate interface, 41
ng generate module, 41
ng generate pipe, 41
ng generate service, 41
ng new, 41
ng serve, 41
npm install, 121
comparison operators, 9–10
Component class, 64–66
component property (route object), 133
components, 42–43, 185–192. See also listings; services
Angular bootstrapper, 44–48
animation application, 172–173
animated.component.css, 175
animated.Component.html, 175
animated.component.ts, 173–174
app.component.ts, 172
app.module.ts, 171–172
folder structure, 171
configuration, 49–50
constructors, 53–54
custom component directives, 98–102
container component, 100
CSS for container component, 101
CSS for root component, 100
HTML for container component, 101
HTML for root component, 99–100
root component, 99
deleting data in, 107–110
dependency injection
building nested components with, 56–58
definition of, 38–39, 56
passing data with, 58–59
sample application with inputs, 59–60
drag-and-drop application
app.component.css, 181–182
app.component.html, 181
app.component.ts, 180–181
drag.component.css, 184
drag.component.html, 184
drag.component.ts, 184
drop.component.css, 183
drop.component.html, 183
drop.component.ts, 182
folder structure, 179–180
emitting custom events from, 104
image zoom application
app.component.html, 177
app.component.ts, 176–177
folder structure, 176
zoomit.component.css, 178
zoomit.component.html, 178
zoomit.component.ts, 177–178
importing, 42–43
inline CSS and HTML in, 51–52
integrating custom services into, 149–150
nested components, 104–106
NgModule, 43–44
selectors, 50
separation of responsibilities, 39
star rating application
app.component.css, 190
app.component.html, 189–190
app.component.ts, 189
app.module.ts, 186
folder structure, 185
mockbackend.service.ts, 186–187
rated-item.component.css, 191–192
rated-item.component.html, 191
rated-item.component.ts, 190–191
ratings.service.ts, 187–188
templates
building, 50–51
external templates, 54–56
components directives, 38, 88
concat() method, 20, 21, 23, 24
conditionals
if statements, 10
switch statements, 11
configuration
components, 49–50
selectors, 50
templates, 50–51
HTTP requests, 117
constant data service, 151–152
app.component.html, 152
app.component.ts, 151
pi.service.ts, 151
constructor.component.ts listing, 53
constructors, 53–54
container component, 100
CSS for, 101
HTML for, 101
container directive
container.component.css, 101
container.component.html, 101
container.component.ts, 100
content, generating with CLI (command-line interface), 40–41
continue statement, 13–14
converting arrays into strings, 24
createAlert() method, 161
createDb() method, 127
createDelete.component.CSS listing, 125–126
createDelete.component.html listing, 125
createDelete.component.ts listing, 123–124
createTimedAlert() method, 161
createUser() method, 122, 124
creating. See also defining
Angular apps
Angular bootstrapper, 44–48
animation application, 171–176
components, 42–43
drag-and-drop application, 179–185
image zoom application, 176–179
NgModule, 43–44
star rating application, 185–192
custom directives
custom attribute directives, 95–98
custom component directives, 98–102
custom pipes, 73–74
Observable object, 110–111
CSS (Cascading Style Sheets)
inline CSS in Angular applications, 51–52
listings
app.component.css, 100, 141, 159, 181–182, 190
attribute.component.css, 94
character.component.css, 108
container.component.css, 101
details.component.css, 109
drag.component.css, 184
drop.component.css, 183
external.css, 55
http.component.CSS, 120–121
outer.css, 57
rated-item.component.css, 191–192
update.component.CSS, 131–132
zoomit.component.css, 178
curly braces ({ }), 10, 14, 75
currency pipe, 69
custom directives, 95
custom attribute directives, 95–98
custom component directives, 98–102
container component, 100
CSS for container component, 101
CSS for root component, 100
HTML for container component, 101
HTML for root component, 99–100
root component, 99
custom events, 104
deleting data with, 107–110
emitting from components, 104
handling with listeners, 104
implementing in nested components, 104–106
custom objects, 18–19
custom pipes, 72–74
custom services, 149
constant data service, 151–152
app.component.html, 152
app.component.ts, 151
pi.service.ts, 151
data transform service, 152–156
app.component.css, 155
app.component.html, 154–155
app.component.ts, 153–154
area-calc.service.ts, 152–153
integrating into applications, 149–150
service that returns a promise, 161–162
shared service, 162–169
app.component.html, 165
app.component.ts, 165
badguys.component.css, 168
badguys.component.html, 168
badguys.component.ts, 167
good-guys.component.css, 167
good-guys.component.html, 166
good-guys.component.ts, 166
shared.service.ts, 163–164
use cases for, 149–150
variable data service, 156–160
app.component.css, 159
app.component.html, 159
app.component.ts, 158–159
random-image.service.ts, 157–158
customevent.component.html listing, 105–106
customevent.component.ts listing, 105
customPipes.component.ts listing, 73–74
custom.pipe.ts listing, 73
D
data, passing with dependency injection, 58–59
data binding, 75
attribute binding, 79
class binding, 79–80
definition of, 38
event binding, 82–85
interpolation, 76–77
property binding, 77–79
style binding, 81–82
two-way binding, 85–86
data changes, detecting with observables, 111–114
Data property (route object), 133
data transform service, 152–156
app.component.css, 155
app.component.html, 154–155
app.component.ts, 153–154
area-calc.service.ts, 152–153
data types
JavaScript, 6–7
TypeScript, 29–30
data.service.ts listing, 122, 127–128
date pipe, 70
debounce() method, 117
declarations metadata, 43, 56
decorators
@NgModule, 43–44, 56
@pipe, 72
decrement operator, 8
defining. See also creating
classes, 32
functions, 14–15
interfaces, 31
routes array, 132–133
selectors, 50
variables, 6
delete() method, 116
deleteChar() method, 107
deleteUser() function, 122
deleteUser() method, 124
deleting data, 107–110
dependency injection
building nested components with, 56–58
definition of, 38–39, 56
passing data with, 58–59
sample application with inputs, 59–60
details.component.css listing, 109
details.component.html listing, 109
details.component.ts listing, 108–109
detecting data changes, 111–114
development environments, 5–6
@directive class, 95
Directive class, 95
directives. See also commands
built-in directives, 87–88
attribute directives, 38, 91–94
components directives, 38, 88
structural directives, 38, 88–91
custom directives, 95
custom attribute directives, 95–98
custom component directives, 98–102
definition of, 87
division operator, 8
doCalc() function, 16
doCircle() method, 153
doRectangle() method, 153
doSquare() method, 153
doTrapezoid() method, 153
doTriangle() method, 153
double curly braces ({{}}), 75
do/while loops, 12
drag-and-drop application
app.component.css, 181–182
app.component.html, 181
app.component.ts, 180–181
drag.component.css, 184
drag.component.html, 184
drag.component.ts, 184
drop.component.css, 183
drop.component.html, 183
drop.component.ts, 182
folder structure, 179–180
drag-item component
app.component.css, 181–182
app.component.html, 181
app.component.ts, 180–181
drag.component.css, 184
drag.component.html, 184
drag.component.ts, 184
drop-item component
app.component.css, 181–182
app.component.html, 181
app.component.ts, 180–181
drop.component.css, 183
drop.component.html, 183
drop.component.ts, 182
dummyDB.JSON listing, 118
E
editors, 5
elements of arrays, adding/removing, 25
emit() method, 104
emitting custom events, 104
entryComponents metadata option (NgModule), 43
enum data type, 30
environment, adding Angular to, 39–40
equal operator, 9
equal sign (=), 9
error handling, 25
finally keyword, 27
throwing errors, 26–27
try/catch blocks, 26
escape codes, 20
event binding, 82–85
event.component.ts listing, 82–84
EventEmitter class, 104
eventHandler() method, 105
events
binding, 82–85
browser events, 103–104
custom events, 104
deleting data with, 107–110
emitting from components, 104
handling with listeners, 104
implementing in nested components, 104–106
export classes
Directive, 95
ZoomDirective, 97
export keyword, 38
exporting modules, 38
exports metadata option (NgModule), 43
expressions, 61–62
basic expressions, 62–63
Component class interaction, 64–66
pipes
built-in pipes, 69–72
custom pipes, 72–74
definition of, 68–69
TypeScript in, 65–68
external templates, 54–56
external.component.ts listing, 55
external.css listing, 55
externalTemplate.html listing, 55
F
\f (form feed) escape code, 20
@fadeState, 173–175
feed() method, 32
finally keyword, 27
first.component.js listing, 48
first.component.ts listing, 46
first.html listing, 45
(focus) event, 103
form feed escape code, 20
formatGreeting() function, 15
forms service, 116
forward slash (/), 8
fromCharCode() method, 20
functions, 14–15. See also methods
anonymous functions, 16
border(), 96
callback functions, 16
changeSize(), 96
defining, 14–15
deleteUser(), 122
doCalc(), 16
formatGreeting(), 15
getRandom(), 156
gotoPage2(), 144–145
greeting(), 15
imageClick(), 178
passing variables to, 15
playLoop(), 111
resolve(), 161
returning values from, 15
selectCharacter(), 107
setTimeout(), 156
soldierOfGondor(), 34
G
generating content with CLI (command-line interface), 40–41
get() method, 116
GET requests
response callback functions, 117
sending, 116–117
getCharacters() method, 163
getItems() method, 187
getObservable() method, 187, 189
getPi() method, 151
getRandom() function, 156
getRandomImage() method, 158
getStarClass() method, 190–191
getUsers() method, 122, 128
Good Guys component
good-guys.component.css, 167
good-guys.component.html, 166
good-guys.component.ts, 166
gotoPage2() function, 144–145
greater than operator, 9
greater than or equal to operator, 9
greeting() function, 15
H
handling custom events, 104
head() method, 116
hitCharacter() method, 163–166
home.component.html listing, 136
home.component.ts listing, 136
HTML (Hypertext Markup Language)
events, Angular syntax for, 103–104
inline HTML in Angular applications, 51–52
listings
animated.Component.html, 175
app.component.html. See app.component.html listing
app.module.ts, 126
attribute.component.html, 93
badguys.component.css, 168
badguys.component.html, 168
character.component.html, 108
container.component.html, 101
createDelete.component.CSS, 125–126
createDelete.component.html, 125
customevent.component.html, 105–106
details.component.html, 109
drag.component.html, 184
drop.component.html, 183
externalTemplate.html, 55
first.html, 45
good-guys.component.css, 167
good-guys.component.html, 166
home.component.html, 136
http.component.html, 119–120
observable.component.html, 113
outer.html, 57
page1.component.html, 145
page2.component.html, 142, 146–147
page3.component.html, 142–143
rated-item.component.html, 191
route2.component.html, 137
update.component.html, 130–131
zoomit.component.html, 178
<router-outlet> tag, 134
http service, 116
GET requests, sending, 116–117
JSON file implementation and access, 118–121
app.module.ts, 119–120
dummyDB.JSON, 118
http.component.CSS, 120–121
http.component.html, 119–120
http.component.ts, 119
PUT requests, sending, 116–117
request configuration, 117
response callback functions, 117
simple mock server implementation, 121–127
app.module.ts, 126
createDelete.component.CSS, 125–126
createDelete.component.html, 125
createDelete.component.ts, 123–124
creating, 121
data.service.ts, 122
user.service.ts, 124–125
simple mock server updates, 127–132
data.service.ts, 127–128
update.component.CSS, 131–132
update.component.html, 130–131
update.component.ts, 128–129
user.service.ts, 129–130
http.component.CSS listing, 120–121
http.component.html listing, 119–120
http.component.ts listing, 119
HttpModule, importing, 119–120
Hypertext Markup Language. See HTML (Hypertext Markup Language)
I
id metadata option (NgModule), 43
IDEs (integrated development environments), 5
if statements, 10
imageClick() function, 178
images
animation application
animated.component.css, 175
animated.Component.html, 175
animated.component.ts, 173–174
app.component.html, 172–173
app.component.ts, 172
app.module.ts, 171–172
drag-and-drop application
app.component.css, 181–182
app.component.html, 181
app.component.ts, 180–181
drag.component.css, 184
drag.component.html, 184
drag.component.ts, 184
drop.component.css, 183
drop.component.html, 183
drop.component.ts, 182
folder structure, 179–180
image zoom application
app.component.html, 177
app.component.ts, 176–177
folder structure, 176
zoomit.component.css, 178
zoomit.component.html, 178
zoomit.component.ts, 177–178
import keyword, 38
importing
modules, 38
ActivatedRoute, 134
AppRoutingModule, 134
Component, 42–43
HttpModule, 119–120
InMemoryDbService, 122, 127
InMemoryWebApiModule, 126–127
NgModule, 43–44
Router, 134, 138
Observable object, 156–158
imports metadata option (NgModule), 43
increment operator, 8
indexed arrays, 30
indexOf() method, 20, 21, 23, 25
inheritance, 33
inline CSS and HTML, 51–52
InMemoryDbService, importing, 122, 127
InMemoryWebApiModule
implementing, 186
importing, 126–127
inner.component.ts listing, 58
Input decorator, 58
input.component.ts listing, 59–60
integrated development environments (IDEs), 5
interface keyword, 31
interfaces
Person, 31
PersonInterface, 32
RatedItem, 187
Stringy, 31
TypeScript, 31–32
interpolation, 76–77
interpolation.component.ts listing, 76–77
interrupting loops, 13–14
intro.ts listing, 52
iterating through arrays, 24
J
JavaScript, 5
arrays
adding items to, 25
combining, 24
converting into strings, 24
iterating through, 24
manipulating, 22–24
methods, 23
removing items from, 25
searching, 25
conditionals
if statements, 10
switch statements, 11
data types, 6–7
development environment, 5–6
error handling, 25
finally keyword, 27
throwing errors, 26–27
try/catch blocks, 26
functions, 14–15
anonymous functions, 16
border(), 96
callback functions, 16
changeSize(), 96
createUser(), 122
defining, 14–15
deleteUser(), 122
doCalc(), 16
formatGreeting(), 15
getRandom(), 156
gotoPage2(), 144–145
greeting(), 15
imageClick(), 178
passing variables to, 15
playLoop(), 111
resolve(), 161
returning values from, 15
selectCharacter(), 107
setTimeout(), 156
soldierOfGondor(), 34
keywords
export, 38
finally, 27
import, 38
new, 17
styles, 51
styleUrls, 54
templateUrl, 54
var, 6
loops, 11
for/in, 13
do/while, 12
for, 12–13
interrupting, 13–14
while, 11–12
methods, 17
addClass, 92
allowDrop(), 182
catch(), 117
changeLoop(), 156
charAt(), 20
charCodeAt(), 20
concat(), 20, 21, 23, 24
createAlert(), 161
createDb(), 127
createTimedAlert(), 161
createUser(), 124
debounce(), 117
definition of, 17
delete(), 116
deleteChar(), 107
deleteUser(), 124
doCircle(), 153
doRectangle(), 153
doSquare(), 153
doTrapezoid(), 153
doTriangle(), 153
emit(), 104
eventHandler(), 105
feed(), 32
fromCharCode(), 20
get(), 116
getCharacters(), 163
getItems(), 187
getObservable(), 187, 189
getPi(), 151
getRandomImage(), 158
getStarClass(), 190–191
getUsers(), 122, 128
head(), 116
hitCharacter(), 163–166
indexOf(), 20, 21, 23, 25
join(), 23, 24
lastIndexOf(), 20, 23
leave(), 173
map(), 117
match(), 20
ngOnInit(), 111, 128, 151, 177, 189
onDrop(), 182
patch(), 116
pop(), 23
post(), 116
preventDefault(), 182
push(), 23
put(), 116
replace(), 20, 22
reverse(), 23
search(), 21
selectUser(), 128
setRating(), 190
shift(), 23
slice(), 21, 23
sort(), 23
split(), 21, 22
subscribe(), 110
substr(), 21
.then(), 118–119
toLowerCase(), 21
toPromise(), 117, 118–119
toString(), 23
toUpperCase(), 21
unshift(), 23
updateRating(), 187–188
updateUser(), 128, 129
valueOf(), 21, 23
objects, 17
Array, 22–25
custom objects, 18–19
prototyping object patterns, 19
String, 19–22
syntax, 17–18
operators, 8
arithmetic operators, 8
assignment operators, 8–9
comparison operators, 9–10
statements
break, 13–14
catch, 26
continue, 13–14
if, 10
return, 15
switch, 11
throw, 26–27
try, 26
strings
combining, 21
converting arrays into, 24
manipulating, 19–21
replacing words in, 22
searching, 21
splitting, 22
string-related methods, 20–21
variables
defining, 6
passing to functions, 15
scope, 16–17
join() method, 23, 24
JSON file implementation and access, 118–121
app.module.ts, 119–120
dummyDB.JSON, 118
http.component.CSS, 120–121
http.component.html, 119–120
http.component.ts, 119
json pipe, 69
K
(keydown) event, 104
(keypress) event, 104
(keyup) event, 104
keywords. See also statements
export, 38
import, 38
new, 17
styles, 51
styleUrls, 54
templateUrl, 54
var, 6
L
lastIndexOf() method, 20, 23
leave() method, 173
less than operator, 9
less than or equal to operator, 9
listeners, 104
listings
animated.component.css, 175
animated.Component.html, 175
animated.component.ts, 173–174
app.component.css
AreaCalcService, 155
custom directive with component, 100
drag-and-drop application, 181–182
RandomImageService, 159
router with navigation bar, 141
star rating application, 190
app.component.html
animation application, 172–173
AreaCalcService, 154–155
custom directive with component, 99–100
drag-and-drop application, 181
image zoom application, 177
PiService, 152
PromiseService, 162
RandomImageService, 159
router with navigation bar, 140
SharedService, 165
star rating application, 189–190
zoom directive, 97–98
app.component.ts
animation application, 172
AreaCalcService, 153–154
custom directive with component, 99
drag-and-drop application, 180–181
image zoom application, 176–177
PiService, 151
PromiseService, 161–162
RandomImageService, 158–159
router with navigation bar, 140
router with parameters, 144
SharedService, 165
simple router application, 135–136
star rating application, 189
app.module.js, 47
app.module.ts
Angular bootstrapper, 46
animation application, 171–172
simple mock server implementation, 119–120, 126
simple router implementation, 134–135
star rating application, 186
app-routing.module.ts
router with navigation bar, 138–139
router with parameters, 144
simple router implementation, 135–136
area-calc.service.ts, 152–153
attribute.component.css, 94
attribute.component.html, 93
attribute.component.ts, 92–93
badguys.component.css, 168
badguys.component.html, 168
badguys.component.ts, 167
basicExpressions.component.ts, 63
builtInPipes.component.ts, 71–72
character.component.css, 108
character.component.html, 108
character.component.ts, 107–108
class.component.ts, 80
classExpressions.component.ts, 64–65
constructor.component.ts, 53
container.component.css, 101
container.component.html, 101
container.component.ts, 100
createDelete.component.CSS, 125–126
createDelete.component.html, 125
createDelete.component.ts, 123–124
customevent.component.html, 105–106
customevent.component.ts, 105
customPipes.component.ts, 73–74
custom.pipe.ts, 73
data.service.ts, 122, 127–128
details.component.css, 109
details.component.html, 109
details.component.ts, 108–109
drag.component.css, 184
drag.component.html, 184
drag.component.ts, 184
drop.component.css, 183
drop.component.html, 183
drop.component.ts, 182
dummyDB.JSON, 118
event.component.ts, 82–84
external.component.ts, 55
external.css, 55
externalTemplate.html, 55
first.component.js, 48
first.component.ts, 46
first.html, 45
good-guys.component.css, 167
good-guys.component.html, 166
good-guys.component.ts, 166
home.component.html, 136
home.component.ts, 136
http.component.CSS, 120–121
http.component.html, 119–120
http.component.ts, 119
inner.component.ts, 58
input.component.ts, 59–60
interpolation.component.ts, 76–77
intro.ts, 52
mockbackend.service.ts, 186–187
nav.component.CSS, 140
nav.component.html, 139
nav.component.ts, 139
observable.component.html, 113
observable.component.ts, 112–113
outer.component.ts, 57
outer.css, 57
outer.html, 57
page1.component.html, 145
page1.component.ts
router with navigation bar, 141
router with parameters, 145
page2.component.html
router with navigation bar, 142
router with parameters, 146–147
page2.component.ts
router with navigation bar, 141
router with parameters, 146
page3.component.html, 142–143
page3.component.ts, 142
person.component.ts, 59
pi.service.ts, 151
promise.service.ts, 161
property.component.ts, 78
random-image.service.ts, 157–158
rated-item.component.css, 191–192
rated-item.component.html, 191
rated-item.component.ts, 190–191
ratings.service.ts, 187–188
route2.component.html, 137
route2.component.ts, 137
shared.service.ts, 163–164
structural.component.ts, 89–90
style.component.ts, 81, 86
typescriptExpressions.component.ts, 67
update.component.CSS, 131–132
update.component.html, 130–131
update.component.ts, 128–129
user.service.ts, 124–125, 129–130
zoom.component.ts, 96–98
zoom.directive.ts, 96–97
zoomit.component.css, 178
zoomit.component.html, 178
zoomit.component.ts, 177–178
loadChildren property (route object), 133
for/in loops, 13
for loops, 12–13
loops, 11
for/in, 13
do/while, 12
for, 12–13
interrupting, 13–14
while, 11–12
lowercase pipe, 69
M
manipulating
arrays, 22–24
strings, 19–21
map() method, 117
match() method, 20
methods. See also functions
addClass(), 92
allowDrop(), 182
catch(), 117
changeLoop(), 156
charAt(), 20
charCodeAt(), 20
concat(), 20, 21, 23, 24
createAlert(), 161
createDb(), 127
createTimedAlert(), 161
createUser(), 122, 124
debounce(), 117
definition of, 17
delete(), 116
deleteChar(), 107
deleteUser(), 124
doCircle(), 153
doRectangle(), 153
doSquare(), 153
doTrapezoid(), 153
doTriangle(), 153
emit(), 104
eventHandler(), 105
feed(), 32
fromCharCode(), 20
get(), 116
getCharacters(), 163
getItems(), 187
getObservable(), 187, 189
getPi(), 151
getRandomImage(), 158
getStarClass(), 190–191
getUsers(), 122, 128
head(), 116
hitCharacter(), 163–166
indexOf(), 20, 21, 23, 25
join(), 23, 24
lastIndexOf(), 20, 23
leave(), 173
map(), 117
match(), 20
ngOnInit(), 111, 128, 151, 177, 189
onDrop(), 182
patch(), 116
pop(), 23
post(), 116
preventDefault(), 182
push(), 23
put(), 116
replace(), 20, 22
reverse(), 23
search(), 21
selectUser(), 128
setRating(), 190
shift(), 23
slice(), 21, 23
sort(), 23
split(), 21, 22
subscribe(), 110
substr(), 21
.then(), 118–119
toLowerCase(), 21
toPromise(), 117, 118–119
toString(), 23
toUpperCase(), 21
unshift(), 23
updateRating(), 187–188
updateUser(), 128, 129
valueOf(), 21, 23
mock back-end service, 186–187
mock web servers
simple JSON file implementation, 118–121
app.module.ts, 119–120
dummyDB.JSON, 118
http.component.CSS, 120–121
http.component.html, 119–120
http.component.ts, 119
simple mock server implementation, 121–127
app.module.ts, 126
createDelete.component.CSS, 125–126
createDelete.component.html, 125
createDelete.component.ts, 123–124
creating, 121
data.service.ts, 122
user.service.ts, 124–125
simple mock server updates, 127–132
data.service.ts, 127–128
update.component.CSS, 131–132
update.component.html, 130–131
update.component.ts, 128–129
user.service.ts, 129–130
mockbackend.service.ts listing, 186–187
modules
Angular, 38
importing
AppRoutingModule, 134
BrowserAnimationsModule, 172
Component, 42–43
HttpModule, 119–120
InMemoryDbService, 122, 127
InMemoryWebApiModule, 126–127
NgModule, 43–44
Router, 138
routing module, 134
TypeScript, 33–34
modulo operator, 8
(mouseover) event, 104
multiplication operator, 8
myCustomEvent, 105
N
\n (new line) escape code, 20
naming conventions, 50
nav.component.CSS listing, 140
nav.component.html listing, 139
nav.component.ts listing, 139
navigating routes, 134
navigation bar, router with, 138–143
app.component.CSS, 141
app.component.html, 140
app.component.ts, 140
app-routing.module.ts, 138–139
nav.component.CSS, 140
nav.component.html, 139
nav.component.ts, 139
page1.component.ts, 141
page2.component.html, 142
page2.component.ts, 141
page3.component.html, 142–143
page3.component.ts, 142
nested components
building with dependency injection, 56–58
custom events in, 104–106
new keyword, 17
new line escape code, 20
ng eject command, 41
ng generate component command, 41
ng generate directive command, 41
ng generate enum command, 41
ng generate guard command, 41
ng generate interface command, 41
ng generate module command, 41
ng generate pipe command, 41
ng generate service command, 41
ng new command, 41
ng serve command, 41
ng-content directive, 98
ngFor directive, 88, 120, 125, 130, 159
ngForm directive, 91
ngIf directive, 88–89
ngModel directive, 91
NgModule, 43–44, 56
ngOnInit() method, 111, 128, 151, 177, 189
ngStyle directive, 91
ngSwitch directive, 88–89
ngSwitchCase directive, 88, 89
ngSwitchDefault directive, 88
not equal operator, 9
not operator, 10
npm install command, 121
null data type
JavaScript, 7
TypeScript, 30
number data type
JavaScript, 7
TypeScript, 29
number pipe, 69
O
object literals, 7
objects, 17. See also methods
Array, 22–25
adding items to, 25
combining, 24
converting into strings, 24
iterating through, 24
manipulating, 22–24
methods, 23
removing items from, 25
searching, 25
custom objects, 18–19
Observable
creating, 110–111
detecting data changes with, 111–114
properties, 17
prototyping object patterns, 19
route, 133
String, 19–22
combining, 21
converting arrays into, 24
escape codes, 20
manipulating, 19–21
methods, 20–21
replacing words in, 22
searching, 21
splitting, 22
syntax, 17–18
Observable object
creating, 110–111
detecting data changes with, 111–114
importing, 156–158
observable.component.html listing, 113
observable.component.ts listing, 112–113
observables
definition of, 110
Observable object
creating, 110–111
detecting data changes with, 111–114
onDrop() method, 182
operators (JavaScript), 8
arithmetic operators, 8
assignment operators, 8–9
comparison operators, 9–10
or operator, 10
outer.component.ts listing, 57
outer.css listing, 57
outer.html listing, 57
outlet property (route object), 133
P
page1.component.html listing, 145
page1.component.ts listing
router with navigation bar, 141
router with parameters, 145
page2.component.html listing
router with navigation bar, 142
router with parameters, 146–147
page2.component.ts listing
router with navigation bar, 141
router with parameters, 146
page3.component.html listing, 142–143
page3.component.ts listing, 142
parameters, router with, 143–147
app.component.ts, 144
app-routing.module.ts, 144
page1.component.html, 145
page1.component.ts, 145
page2.component.html, 146–147
page2.component.ts, 146
parent components, deleting data in, 107–110
parentheses ( ), 10, 14, 82, 103
passing data
with dependency injection, 58–59
variables to functions, 15
patch() method, 116
path property (route object), 133
percent sign (%), 8
Person interface, 31
person.component.ts listing, 59
PersonInterface, 32
pipe class, 72
@pipe decorator, 72
pipe symbol (|), 72
pipes
built-in pipes
builtInPipes.component.ts, 71–72
table of, 69–70
custom pipes, 72–74
definition of, 68–69
PiService, 151–152
app.component.html, 152
app.component.ts, 151
pi.service.ts, 151
pi.service.ts listing, 151
playLoop() function, 111
plus sign (+), 8
pop() method, 23
post() method, 116
preventDefault() method, 182
PromiseService, 161–162
promise.service.ts listing, 161
properties
binding, 77–79
definition of, 17
property binding, 77–79
property.component.ts listing, 78
prototyping object patterns, 19
providers metadata option (NgModule), 43
push() method, 23
put() method, 116
PUT requests
response callback functions, 117
sending, 116–117
Q-R
\r (carriage return) escape code, 20
RandomImageService, 156–160
app.component.css, 159
app.component.html, 159
app.component.ts, 158–159
random-image.service.ts, 157–158
random-image.service.ts listing, 157–158
rated-item component, 189–190
rated-item.component.css, 191–192
rated-item.component.html, 191
rated-item.component.ts, 190–191
RatedItem interface, 187
ratings.service.ts listing, 187–188
redirectTo property (route object), 133
removing items from arrays, 25
replace() method, 20, 22
replacing words in strings, 22
requests
configuration, 117
GET requests, 116–117
PUT requests, 116–117
response callback functions, 117
resolve() function, 161
Resolve property (route object), 133
response callback functions (HTTP), 117
responsibilities, separation of, 39
return statement, 15
return values, 15
reverse() method, 23
root component (custom directive), 99
CSS for, 100
HTML for, 99–100
route object, 133
route2.component.html listing, 137
route2.component.ts listing, 137
Router, importing, 134
Router module, importing, 138
router service, 116
ActivatedRoute, importing, 134
route navigation, 134
route object parameters, 133
Router, importing, 134
router with navigation bar, 138–143
app.component.CSS, 141
app.component.html, 140
app.component.ts, 140
app-routing.module.ts, 138–139
nav.component.CSS, 140
nav.component.html, 139
nav.component.ts, 139
page1.component.ts, 141
page2.component.html, 142
page2.component.ts, 141
page3.component.html, 142–143
page3.component.ts, 142
router with parameters, 143–147
app.component.ts, 144
app-routing.module.ts, 144
page1.component.html, 145
page1.component.ts, 145
page2.component.html, 146–147
page2.component.ts, 146
routes array, defining, 132–133
routing module, including, 134
simple router implementation, 134–137
app.component.ts, 135–136
app.module.ts, 134–135
app-routing.module.ts, 135–136
home.component.html, 136
home.component.ts, 136
route2.component.html, 137
route2.component.ts, 137
<router-outlet> tag, 134
routes array, defining, 132–133
routing module, including, 134
runGaurdsAndResolvers property (route object), 133
S
schemas metadata option (NgModule), 43
scope of variables, 16–17
search() method, 21
searching
arrays, 25
strings, 21
SecretAgent class, 33
selectCharacter() function, 107
selector option (components), 49
selectors, 50
selectUser() method, 128
sending HTTP requests, 116–117
separation of responsibilities, 39
servers. See mock web servers
services
animate, 116
constant data service, 151–152
app.component.html, 152
app.component.ts, 151
pi.service.ts, 151
data transform service, 152–156
app.component.css, 155
app.component.html, 154–155
app.component.ts, 153–154
area-calc.service.ts, 152–153
definition of, 39
forms, 116
http, 116
GET requests, sending, 116–117
JSON file implementation and access, 118–121
PUT requests, sending, 116–117
request configuration, 117
response callback functions, 117
simple mock server implementation, 121–127
simple mock server updates, 127–132
integrating into applications, 149–150
mock back-end service, 186–187
purpose of, 115
ratings service, 187–188
router, 116
ActivatedRoute, importing, 134
route navigation, 134
route object parameters, 133
Router, importing, 134
router with navigation bar, 138–143
router with parameters, 143–147
routes array, 132–133
routing module, including, 134
simple router implementation, 134–137
service that returns a promise, 161–162
shared service, 162–169
app.component.html, 165
app.component.ts, 165
badguys.component.css, 168
badguys.component.html, 168
badguys.component.ts, 167
good-guys.component.css, 167
good-guys.component.html, 166
good-guys.component.ts, 166
shared.service.ts, 163–164
use cases for, 149–150
UserService, 129–130
variable data service, 156–160
app.component.css, 159
app.component.html, 159
app.component.ts, 158–159
random-image.service.ts, 157–158
setRating() method, 190
setTimeout() function, 156
shared service, 162–169
app.component.html, 165
app.component.ts, 165
badguys.component.css, 168
badguys.component.html, 168
badguys.component.ts, 167
good-guys.component.css, 167
good-guys.component.html, 166
good-guys.component.ts, 166
shared.service.ts, 163–164
SharedService. See shared service
shared.service.ts listing, 163–164
shift() method, 23
slice() method, 21, 23
slice:start:end pipe, 69
soldierOfGondor() function, 34
sort() method, 23
split() method, 21, 22
splitting strings, 22
star rating application
app.component.css, 190
app.component.html, 189–190
app.component.ts, 189
app.module.ts, 186
folder structure, 185
mockbackend.service.ts, 186–187
rated-item.component.css, 191–192
rated-item.component.html, 191
rated-item.component.ts, 190–191
ratings.service.ts, 187–188
statements. See also keywords
break, 13–14
catch, 26
continue, 13–14
finally, 27
if, 10
return, 15
switch, 11
throw, 26–27
try, 26
String object, 19–22
combining, 21
converting arrays into, 24
escape codes, 20
manipulating, 19–21
methods, 20–21
replacing words in, 22
searching, 21
splitting, 22
strings
JavaScript, 6
combining, 21
converting arrays into, 24
escape codes, 20
manipulating, 19–21
methods, 20–21
replacing words in, 22
searching, 21
splitting, 22
TypeScript, 29
Stringy interface, 31
structural directives, 38, 88–91
definition of, 87
ngFor, 88
ngIf, 88–89
ngSwitch, 88–89
ngSwitchCase, 88, 89
ngSwitchDefault, 88
structural.component.ts, 89–90
structural.component.ts listing, 89–90
style binding, 81–82
style.component.ts listing, 81, 86
styles, binding, 81–82
styles keyword, 51
styles option (components), 50
stylesUrls option (components), 50
styleUrls keyword, 54
(submit) event, 103
subscribe() method, 110
substr() method, 21
substrings, searching for, 21
subtraction operator, 8
switch statements, 11
T
(tab) escape code, 20
tab escape code, 20
tags, <router-outlet>134
template option (components), 50
templates
building, 50–51
external templates, 54–56
templateUrl keyword, 54
templateUrl option (components), 50
.then() method, 118–119
throw statement, 26–27
throwing errors, 26–27
tilde (~), 50–51
toLowerCase() method, 21
toPromise() method, 117, 118–119
toString() method, 23
toUpperCase() method, 21
try statement, 26
two-way binding, 85–86
types. See data types
TypeScript, 29. See also listings
in Angular expressions, 65–68
classes
defining, 32
inheritance, 33
data types, 29–30
directives, 108–109
functions, 34–35
interfaces, 31–32
modules, 33–34
typescriptExpressions.component.ts listing, 67
U
unshift() method, 23
update.component.CSS listing, 131–132
update.component.html listing, 130–131
update.component.ts listing, 128–129
updateRating() method, 187–188
updateUser() method, 128, 129
updating mock web server items, 127–132
data.service.ts, 127–128
update.component.CSS, 131–132
update.component.html, 130–131
update.component.ts, 128–129
user.service.ts, 129–130
uppercase pipe, 69
UserService, 129–130
user.service.ts listing, 124–125, 129–130
V
valueOf() method, 21, 23
var keyword, 6
variable data service, 156–160
app.component.css, 159
app.component.html, 159
app.component.ts, 158–159
random-image.service.ts, 157–158
variables, 6
passing to functions, 15
scope, 16–17
viewProviders option (components), 50
Visual Studio Code, 40
void data type, 30
W
web applications. See components; services
web browsers. See browsers
web servers. See mock web servers
while loops, 11–12
words, replacing in strings, 22
X-Y-Z
zoom application
app.component.html, 177
app.component.ts, 176–177
folder structure, 176
zoomit.component.css, 178
zoomit.component.html, 178
zoomit.component.ts, 177–178
zoom directive, 95–98
ZoomDirective export class, 97
zoom.directive.ts listing, 96–97
zoomit component
zoomit.component.css, 178
zoomit.component.html, 178
zoomit.component.ts, 177–178
Code Snippets