TypeScript 2.x By Example

4.8 (4 reviews total)
By Sachin Ohri
    Advance your knowledge in tech with a Packt subscription

  • Instant online access to over 7,500+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Our First Application – Sports News Combinator

About this book

The TypeScript language, compiler, and open source development toolset brings JavaScript development up to the enterprise level. It allows you to use ES5, ES6, and ES7 JavaScript language features today, including classes, interfaces, generics, modules, and more. Its simple typing syntax enables building large, robust applications using object-oriented techniques and industry-standard design principles.

This book aims at teaching you how to get up and running with TypeScript development in the most practical way possible. Taking you through two exciting projects built from scratch, you will learn the basics of TypeScript, before progressing to functions, generics, promises, and callbacks. Then, you’ll get to implement object-oriented programming as well as optimize your applications with effective memory management. You’ll also learn to test and secure your applications, before deploying them. Starting with a basic SPA built using Angular, you will progress on to building, maybe, a Chat application or a cool application. You’ll also learn how to use NativeScript to build a cool mobile application. Each of these applications with be explained in detail, allowing you to grasp the concepts fast.

By the end of this book, you will have not only built two amazing projects but you will also have the skills necessary to take your development to the next level.

Publication date:
December 2017
Publisher
Packt
Pages
372
ISBN
9781787280038

 

Our First Application – Sports News Combinator

In the last chapter, we got a glimpse into the world of TypeScript. We looked at the features of TypeScript, which allow us to write more manageable, robust, and error-free code. TypeScript is a powerful language that provides the right balance between the flexibility of JavaScript and features, such as types and interfaces, which provide checks at design and compile time.

In this chapter, we will start by digging deeper into the feature set of TypeScript, and will also introduce the Angular framework. As with the subject of this book, we will use real-world examples to gain a better understanding of the features.

This chapter will focus on the following topics:

  • Sports News Combinator (SNC): We will start by introducing our first application and its feature set, which we will build.
  • Types in TypeScript: Types play an important role in TypeScript, and we will delve deeper into the various types available in TypeScript, type inference, and type declaration.
  • Classes in TypeScript: To be able to build robust web applications, we have classes. TypeScript implements classes to provide the object-oriented feature.
  • Introduction to Angular: The SNC application is built with TypeScript and Angular, so it is important to introduce Angular and its basic concepts, such as components and data binding.
  • Project setup, configuration, and code setup: In this section, we will start building our application by first looking at various ways to create single-page applications (SPAs) with Angular, and then using the Angular CLI to create our application's skeleton.
  • The architecture of SNC: We will look at the high-level architecture of SNC and discuss the various components that will be created.
  • Building our first component: We will be creating our first component, which will be used to display the news content on the page.

By the end of this chapter, we will have a simple working app with hardcoded data, as well as an understanding of types in TypeScript, and the basic fundamentals of Angular.

 

Sports News Combinator (SNC)

SNC is a single-page web application that provides a unified interface to view the latest sports news from various news outlets. We will be fetching news from NFL, Fox Sports, ESPN, and BBC Sport. We will have four tabs in SNC, each providing the top 10 articles from the respective news outlet. When the user clicks on any of the article links, SNC will redirect the user to the respective website.

This application will be large enough to showcase application features, and small enough not to distract us with the intricacies of applications, and will help us learn the fundamental concepts of TypeScript and Angular.

The following screenshot shows the final version of our application:

Downloading the code

The code for SNC can be downloaded from GitHub at https://github.com/sachinohri/SportsNewsCombinator.git. We will build our application incrementally, with each chapter adding features while discussing the concepts of TypeScript and Angular. So, it makes sense that we provide code for each chapter as well, apart from the final application. To achieve this goal, we have created multiple folders under the main master branch, with each folder providing the final code, which we will create at the end of each chapter. The naming convention for each folder is based on the chapter number.

For this chapter, you can find the code in the Chapter 02 folder, as shown in the following screenshot:

The feature set of SNC

In this chapter, we will be focusing on creating the bare minimum of our application to showcase the features of TypeScript and Angular. SNC will have the following functionalities by the end of this chapter:

  • The application will have just one tab to show the news from the NFL network.
  • Data in this tab will be hardcoded just to show how data binding works. We will be making a live web service call in Chapter 4, Sports New Combinator - the Final Version.
  • We will design a single component for our application, which will host the main content.

 

Type System

If there is one feature in TypeScript that stands out from its competitor, it is Type System, and how TypeScript uses types to help write better code. Types in TypeScript are one of the easiest features to understand and use, thus providing the maximum productivity boost for a new developer to TypeScript.

To develop any application with TypeScript, understanding types and their features is very important. Hence, we will look at the following topics in this section, which will then help us when we start working on our application:

  • Variables: We will start by looking at how to declare variables and constants in TypeScript. We will also look at the let and const keywords, which were introduced in ES 2015 to provide better scoping.
  • Types: We will then shift our focus to looking at types provided by TypeScript, which include both primitive and custom types.
  • Type inference: Then we will look at how TypeScript uses type inference to help identify the types.
  • Type compatibility: TypeScript has a feature wherein we can relate types based on members only; we will take a look at this with an example.
Types are a TypeScript concept and are not emitted in the transpiled JavaScript. They are only used at design and compile time.

Variables

If you have done any JavaScript programming, you will be aware of the var keyword for declaring variables. In ES 2015, a couple of new keywords were introduced to allow declaring variables, namely let and const. The var keyword allowed us to declare a variable, but it had its quirks with regard to how scoping and access to the variables worked; let tries to solve this problem.

The var keyword

Variables declared with the var keyword have a global scope in which they are declared; this means that they can be accessed by any function sharing the same scope. The following example shows the scope of the variable value in innerFunction:

Also, variables declared with the var keyword are subject to hoisting. This means that if we declare a variable at the end of a function, the runtime will hoist it to the top and we will not have any error if we would have used that variable before being declared. In the following example, we see an example of hoisting. Although the value variable was declared at line 9, we were able to access it at lines 3 and 6. When this function is executed, the JavaScript runtime hoists the variable declaration to the top of the function, and hence, is available at lines 3 and 6. The output of the following code will be 1 and 0 respectively:

Let and const keywords

The let and const keywords solve these problems by providing block scoping for the variables, and do not support hoisting. Block scoping means that the scope of a variable is restricted to the scope in which it is declared, which is normally defined by curly braces. So, if a variable is defined inside a loop or an if condition, that variable is not available outside this block, as seen in the following example. Line 6 throws an exception of x is not defined, but we do get the correct response of 10 on line 4:

This helps reduce errors in code because we make sure we are using the variables in the correct scope. Also, the let keyword does not support hoisting, which means that variables are not moved to the top at runtime. They are accessible only after they are declared.

The const keyword is another way to declare variables and follows the same scoping principles as the let keyword. The only difference between const and let is that the values declared with const cannot change once they are bound. So, if you know that the variable you are declaring cannot and should not be allowed to reassign, then declare it with const, else use the let keyword.

Types in TypeScript

The JavaScript language does not have a concept of explicitly defining types of variables which end up being one of the main reasons for errors at runtime. We can assign one type to a variable and then later assign a different type to the same variable. TypeScript, with its type annotation, allows us to assign types to each variable, function, object, or class. Types act as a contract, which that variable has to follow, and the TypeScript compiler makes sure that there are no deviations from this contract. TypeScript does this with static and dynamic type checking. Types provide a set of rules which the compiler needs to follow for that variable; these rules also allow an autosuggest feature in IDEs by providing the most relevant options available. For example, by having types, we can make sure that while calling a function, we are passing the right set of variables.

TypeScript is an optional statically typed language, which means that it is not mandatory to assign types to each variable or function. This is why every JavaScript code is a valid TypeScript code. TypeScript provides a way to infer types for the variable based on the value assigned to the variable or the code flow. TypeScript will try to infer the best possible type, and then have checks in place to make sure that all the further operations do not contradict with the type. TypeScript also provides an option to explicitly opt out of the type for a variable by assigning the any keyword. For a variable with type any, TypeScript does not perform any type checking. This feature allows us to have existing JavaScript migrated to TypeScript without any issues.

TypeScript emits JavaScript even if there are type errors at compile time, allowing us to progressively update the JavaScript code.

Type annotation

To specify a type to a variable or a function, TypeScript provides a syntax for defining a type preceded by a colon. Type annotation comes after the variable identifier. Types can be primitive types, or arrays, or complex types using classes and interfaces. The following example shows the basic syntax of defining types of variables and functions:

let num: number=42;
function example(name: string, age:number): number{
return 42;
}

In the first line, when defining a num variable, it's optional to assign a value as well. In the function example, we see that we can define the type of the input parameter, and also for the return value. This helps us in making sure that all function calls are maintaining the correct signature contract.

Primitive types

TypeScript primitive types relate very closely to the types in JavaScript and follow the same principles. The primitive types available in TypeScript are as follows.

Number

A number data type can contain a double precision 64-bit floating point value. In TypeScript, the number has the same meaning as in JavaScript and represents all numbers, including decimals and hexadecimal. The following is an example of a number variable:

let num:number = 42;
let decimal = 42.0;

String

The string data type represents textual data in UTF-16 format. To assign a string value to a variable, we use single (') or double (") quotes. We can also create a string that spans multiple lines, and is called a template string. The following is an example of declaring strings:

let firstName: string = 'John';
let templateHTML: string = `
<h1>Title</h1>`

In the preceding code, templateHTML is an example of using a template string. This is one of the features that is very frequently used in Angular to define inline templates for its components. We will see these when we start working on our application.

The strings also have an ability to add dynamic expression in its definition, as shown in the following example. The result variable will be Top 10 news feed from ESPN:

let news: string = "ESPN";
let count: number = 10;
let result: string = `Top ${count} news feed from ${news}.`
console.log(result);

The preceding code, when transpiled to JavaScript, produces the following output:

var news = "ESPN";
var count = 10;
var result = "Top " + count + " news feed from " + news + ".";
console.log(result);

Boolean

The boolean data type can be assigned a true or false value as shown in the following example:

let hasvalues: boolean = false;

Arrays

Like JavaScript, TypeScript has an array type to allow assignment of multiple values. The array is specified by adding a square bracket after the type. Every time a new value is added to an array, the compiler checks for type compatibility and alerts if there is a type mismatch. The following is an example of defining an array:

let scores:number[] = [10,20,30,40];

Arrays are accessed based on zero index, which means that the first element is at zeroth index, as shown here:

let scores:number[] = [10,20,30,40];
console.log(scores[0]);

The output of the console statement will be the value 10.

Tuples

Tuples can be seen as an advanced type of an array wherein we can have an array with elements not of the same type. For example, we can have any tuple that will have the first element of type string and the second element as a number, as shown here:

let details:[string, number];
details= ['John', 42];

The preceding code allows us to manage different data types in a single structure, which provides flexibility.

Any

The any keyword is a special type in TypeScript that allows us to opt out of type checking for that variable. This type is very useful when we are migrating the old JavaScript code to TypeScript. We can have the variables defined as any, and TypeScript will not perform any type checking on those. The following example shows the use of the any type:

let item: any;
item = 10;
item = 'John';
item = [10,20,30];

In the preceding code, the compiler does not complain when we assign a number, string, or array to the same variable.

It is recommended to not use any type in TypeScript code until and unless we are in the process of migrating the code from JavaScript. Having the any type takes away all the benefits of compile-time type checking from our code, which can result in unintended behavior.

Void

The void keyword is used to represent a scenario where there is no type. This is useful in the case of functions that do not return any value. These functions are annotated with void as a return type. In the following example, the doSomething function does not return any value, and hence has a void as return type:

function doSomething(num: number):void{
console.log(num);
}

Null and undefined

The null and undefined types are special types that can be assigned to any variable. They are not very useful on their own, as seen in the following example:

let value = null;
value = 42;

Here, the value variable is of the any type, because null is a subtype of all the types and the compiler assigns any to the variable.

Union types

Most of the time, we are aware of what type of data a specific variable can hold, and we can annotate the said variable with that type. This helps in type checking at compile time, and makes sure we don't misuse the variable. But there are times when a variable may not be confined to one specific type, but can have multiple types of values. This is common in scenarios where we are migrating JavaScript code, or using reference of JavaScript libraries.

TypeScript has the union type to solve this problem. A union type allows us to define a variable with multiple types; for example, a variable can have number and string types. This is achieved by using the pipe (|) symbol between the types, as shown here:

let data : string | number;
data = 10;
data = 'John';

Here, the data variable can hold both number and string, which allows us to have the flexibility to use both data types. The TypeScript compiler makes sure that it alerts us if we try to assign a type of value that was not defined.

Like union types, we have intersection types, which allow us to combine multiple types into one type. This is mostly used when we are using classes and interfaces for type declaration, hence we will look into this type when we discuss interfaces in the subsequent chapter.

Type inference

As we discussed in the Types in TypeScript section, TypeScript is an optional statically typed language, which means that TypeScript does provide types, but explicitly assigning types to variables is optional. TypeScript has an ability to infer types if not declared. Let's look at an example:

let firstName = "John";
firstName = 10;

In the line firstName = 10, the compiler alerts us with the error that the variable firstName is a string, and a number cannot be assigned to a string. How does TypeScript identity this mismatch? TypeScript uses type inference to identify the type for the firstName variable.

In this case, TypeScript identified based on the assignment of the value at the time of variable declaration. If we had not assigned "John" to the firstName variable, the type inferred by TypeScript would have been any, as in the example shown here:

let lastName;
lastName = 10;
lastName = 'jj';

This is called type inference through declaration. Another place where you can see type inference in action is the return type of a function. TypeScript looks at the code and, based on the code flow path, decides the best suitable type. The following is one such example:

function doSomething(num:number){
return "name";
}

In this case, TypeScript infers the return type as the string. Type inference is very useful in cases when we are working on legacy code of JavaScript; TypeScript will make sure to infer types for variables and functions based on the code flow.

Type checking

Once TypeScript has identified the types, it uses these for type checking in the program. TypeScript checks if we try to assign a type of value to a variable that contradicts the type defined for that variable, or when a function is called, TypeScript checks if we are passing correct types for the parameters and the return value is being assigned to the correct type of variable. The only exception to this type checking is the any keyword. If a variable or property is defined with the any keyword, the TypeScript compiler does not perform type checking for that variable.

Take a look at the following example of type checking:

let age:number;
age=10;
age="42"; //Compile Error: string can not be assigned to a number

In the preceding example, the TypeScript compiler alerts us on the last line with the message that 42 can not be assigned to a number, because although we are passing a number, we are passing it as the string. TypeScript, unlike JavaScript, does not coerce the types. TypeScript not only does type checking for primitive types, but also for arrays and custom types such as classes. We will look at an example of classes in the next chapter.

Apart from the types we have discussed in the preceding sections, there are other types in TypeScript as well, such as enum, generics, intersection types, and optional types. We will be looking into these types as and when we use them in our example application.

 

Classes in TypeScript

If we are developing any application using TypeScript, be it a small-scale or a large-scale application, we will use classes to manage our properties and methods. Prior to ES 2015, JavaScript did not have the concept of classes, and we used functions to create class-like behavior. TypeScript introduced classes as part of its initial release, and now we have classes in ES6 as well. The behavior of classes in TypeScript and JavaScript ES6 closely relates to the behavior of any object-oriented language that you might have worked on, such as Java or C#.

Object-oriented programming in TypeScript

Object-oriented programming allows us to represent our code in the form of objects, which themselves are instances of classes holding properties and methods. Classes form the container of related properties and their behavior. Modeling our code in the form of classes allows us to achieve various features of object-oriented programming, which helps us write more intuitive, reusable, and robust code. Features such as encapsulation, polymorphism, and inheritance are the result of implementing classes.

TypeScript, with its implementation of classes and interfaces, allows us to write code in an object-oriented fashion. This allows developers coming from traditional languages, such as Java and C#, feel right at home when learning TypeScript.

Understanding classes

Prior to ES 2015, JavaScript developers did not have any concept of classes; the best way they could replicate the behavior of classes was with functions. The function provides a mechanism to group together related properties and methods. The methods can be either added internally to the function, or using the prototype keyword. The following is an example of such a function:

function Name (firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.fullName = function() {
return this.firstName + ' ' + this.lastName ;
};
}

In this preceding example, we have the fullName method encapsulated inside the Name function. Another way of adding methods to functions is shown in the following code snippet with the prototype keyword:

function Name (firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
Name.prototype.fullName = function() {
return this.firstName + ' ' + this.lastName ;
};

These features of functions did solve most of the issues of not having classes, but most of the dev community has not been comfortable with these approaches.

Classes make this process easier. Classes provide an abstraction on top of common behavior, thus making code reusable. The following is the syntax for defining a class in TypeScript:

The syntax of the class should look very similar to readers who come from an object-oriented background. To define a class, we use a class keyword followed by the name of the class. The News class has three member properties and one method. Each member has a type assigned to it, and has an access modifier to define the scope. On line 10, we create an object of a class with the new keyword. Classes in TypeScript also have the concept of a constructor, where we can initialize some properties at the time of object creation. We will look at constructors and other concepts of classes in Chapter 3, Sports News Combinator – Adding Features.

Access modifiers

Once the object is created, we can access the public members of the class with the dot operator. Note that we cannot access the author property with the espn object because this property is defined as private. TypeScript provides three types of access modifiers.

Public

Any property defined with the public keyword will be freely accessible outside the class. As we saw in the previous example, all the variables marked with the public keyword were available outside the class in an object. Note that TypeScript assigns public as a default access modifier if we do not assign any explicitly. This is because the default JavaScript behavior is to have everything public.

Private

When a property is marked as private, it cannot be accessed outside of the class. The scope of a private variable is only inside the class when using TypeScript. In JavaScript, as we do not have access modifiers, private members are treated similarly to public members.

Protected

The protected keyword behaves similarly to private, with the exception that protected variables can be accessed in the derived classes. The following is one such example:

class base{
protected id: number;
}
class child extends base{
name: string;
details():string{
return `${name} has id: ${this.id}`
}
}

In the preceding code, we extend the child class with the base class, and have access to the id property inside the child class. If we create an object of the child class, we will still not have access to the id property outside.

Readonly

As the name suggests, a property with a readonly access modifier cannot be modified after the value has been assigned to it. The value assigned to a readonly property can only happen at the time of variable declaration or in the constructor. We will look at constructors in Chapter 3, Sports News Combinator – Adding Features; here, we will see an example of a readonly property when initialized at the time of declaration:

In the above code, line 5 gives an error stating that property name is readonly, and cannot be an assigned value.

Transpiled JavaScript from classes

While learning TypeScript, it is important to remember that TypeScript is a superset of JavaScript, and not a new language on its own. Browsers can only understand JavaScript, so it is important for us to understand the JavaScript that is transpiled by TypeScript. TypeScript provides an option to generate JavaScript based on the ECMA standards. You can configure TypeScript to transpile into ES5 or ES6 (ES 2015) and even ES3 JavaScript by using the flag target in the tsconfig.json file. We discussed this setting in Chapter 1, Getting Started with TypeScript. The biggest difference between ES5 and ES6 is with regard to the classes, let, and const keywords which were introduced in ES6.

Even though ES6 has been around for more than a year, most browsers still do not have full support for ES6. So, if you are creating an application that would target older browsers as well, consider having the target as ES5.

So, the JavaScript that's generated will be different based on the target setting. Here, we will take an example of class in TypeScript and generate JavaScript for both ES5 and ES6. The following is the class definition in TypeScript:

This is the same code that we saw when we introduced classes in the Understanding Classes section. Here, we have a class named News that has three members, two of which are public and one private. The News class also has a format method, which returns a string concatenated from the member variables.

Then, we create an object of the News class in line 10 and assign values to public properties. In the last line, we call the format method to print the result.

Now let's look at the JavaScript transpiled by TypeScript compiler for this class.

ES6 JavaScript

ES6, also known as ES 2015, is the latest version of JavaScript, which provides many new features on top of ES5. Classes are one such feature; JavaScript did not have classes prior to ES6. The following is the code generated from the TypeScript class, which we saw previously:

If you compare the preceding code with TypeScript code, you will notice minor differences. This is because classes in TypeScript and JavaScript are similar, with just types and access modifiers additional in TypeScript. In JavaScript, we do not have the concept of declaring public members. The author variable, which was defined as private and was initialized at its declaration, is converted to a constructor initialization in JavaScript. If we had not have initialized author, then the produced JavaScript would not have added author in the constructor.

ES5 JavaScript

ES5 is the most popular JavaScript version supported in browsers, and if you are developing an application that has to support the majority of browser versions, then you need to transpile your code to the ES5 version. This version of JavaScript does not have classes, and hence the transpiled code converts classes to functions, and methods inside the classes are converted to prototypically defined methods on the functions.

The following is the code transpiled when we have the target set as ES5 in the TypeScript compiler options:

As discussed earlier, the basic difference is that the class is converted to a function. The interesting aspect of this conversion is that the News class is converted to an immediately invoked function expression (IIFE). An IIFE can be identified by the parenthesis at the end of the function declaration, as we see in line 9 in the preceding code snippet. IIFEs cause the function to be executed immediately, and help to maintain the correct scope of a function rather than declaring the function in a global scope. Another difference was how we defined the method format in the ES5 JavaScript. The prototype keyword is used to add the additional behavior to the function, which we see here.

A couple of other differences you may have noticed include the change of the let keyword to var, as let is not supported in ES5. All variables in ES5 are defined with the var keyword. Also, the format method now does not use a template string, but standard string concatenation to print the output.

TypeScript does a good job of transpiling the code to JavaScript while following recommended practices. This helps in making sure we have a robust and reusable code with minimum error cases.

 

SNC – 101

It's time to jump in over our heads by building our first application. At the start of the chapter, we briefly discussed what the application is all about and how the finished product will look. We will be building this application gradually, starting in this chapter and then adding features to the application in Chapter 3, Sports News Combinator - Adding Features, and Chapter 4, Sports News Combinator - the Final Version. With each new feature, we will first discuss the feature and then implement it.

SNC is an SPA built with Angular and TypeScript. We will be using Angular 4 as our frontend framework, and all the code written in Angular will be in TypeScript. This book does not assume that the reader is proficient in Angular, and hence we will be explaining Angular concepts as we go along.

In the second-half of this chapter, we will focus on the following items of our SNC application:

  • Introduction to Angular: As our application is built on top of the Angular framework, it makes sense for us to first understand the basics of Angular.
  • First step: To start building the application, the first step is to set up the code structure. We will briefly discuss the multiple ways to set up Angular code; more details will be in Chapter 8, Trello – Using Angular CLI.
  • Building our first component: Once the basic code is set up, we will start developing our application by building our first component.

By the end of this chapter, we will have one simple component to display a list of data with images. We are intentionally not adding many features to our application in this chapter because we would like to have more focus on the concepts of Angular and TypeScript. Once we have our basics clear, it will be very easy to look at other features and implement them in our application.

Angular – the superhero framework

In this book, we will be creating three applications, and all the applications will be built with the Angular and TypeScript framework. So, it makes sense for us to spend some time understanding what Angular is, and its basic concepts.

In this section, we will learn just enough concepts to help us start with our first application. In subsequent chapters, as we add features to our applications, we will look at other features of Angular along with TypeScript in detail.

SPAs

In the last couple of decades, web applications have come a long way, from static web applications to web applications with some JavaScript, to jQuery, where we were building dynamic web applications. As the need for web applications increased, technology also evolved to handle the ever-changing needs. Earlier, it was fine to go to the server for each user request, for each page navigation. But, as the need changed, we were looking for ways to make our web applications more fluid, have shorter load time, and reduce the number of requests to the server.

In came SPAs, which provided just the right concepts to improve application performance. The basic premise of an SPA is to have a single HTML page, and just keep swapping the inner content of HTML as the user interacts with the application rather than always loading a whole new page. This approach lets us reduce the request count, reduce the size of the application, and in turn, increases application responsiveness.

Angular is not the only SPA framework on the market at the moment; there are other frameworks such as React, Aurelia, and Vue, which also try to provide a mechanism to create SPAs, though Angular is the most popular one.

Angular – the concepts

Angular is an open source JavaScript/TypeScript framework for building rich client-side applications. Angular uses HTML, CSS, and TypeScript or JavaScript as its building blocks. If you have used jQuery before and are wondering how Angular differentiates itself from jQuery, then you can look at the features it provides. Angular is a full-fledged web application development, unlike jQuery, which is more of a wrapper for JavaScript functions helping in providing a common API for handling different browsers.

Angular provides features to create HTML pages and embed CSS into them, routing to help navigate between pages, services to provide an interface to interact with the backend, and components to stitch all these together. Angular is an opinionated framework, in the sense that it provides guidance on how we should create web applications.

We can easily build our web applications without using Angular as our framework in just plain JavaScript but, in doing so, we would end up defining all the underlying features that can help develop the application. Angular provides many standout features over creating custom frameworks for web applications, as shown in the following diagram:

  • Adds power to the HTML: Angular provides structural directives, which help add flexibility to HTML. With the help of Angular, we can make our HTML more expressive.
  • Better data binding with models: Angular provides a mechanism to bind data models with UI, and help track changes. It has features such as one-way binding and two-way binding, which allows applications to set up a channel between the models and their respective UI elements.
  • Faster load time: Angular has one of the fastest load times, which allows for better rendering and more fluid applications.
  • Reusability: One of the guiding principles of Angular design is its ability to help create a modular design. Angular is designed in a modular way, wherein each feature of Angular is available as a separate module to help manage the dependencies. Modularity allows building components and features that are reusable.
  • Integrates well with backend systems: Angular has specific functionalities that provide interfaces to help communicate with backend servers.
  • Futureproof: Angular follows all the modern practices. It takes advantage of the latest features in JavaScript and TypeScript such as classes, interfaces, and decorators.
  • Better productivity: With all the features of Angular, you will see the productivity improving exponentially when developing any web application. Angular provides a framework that makes it easy to start and implement features and functionalities.

Angular – the architecture

Angular is a modular framework that provides separation of concerns with regard to features and technology. All Angular features are also managed in separate modules; you have a core module, which is responsible for basic features such as components and NgModule, then there are modules for services, pipes, and internationalization, among others. This provides us with the opportunity to create our applications with Angular in more modular fashion to provide us with reusability and ease of use.

Angular application on a high level is comprised of components and services that help us create features and bind them together to make an application. Multiple components can be clubbed together in a module to provide a functionality. For example, we can have a component for report filter and a component for report result. Both these components can be bound together inside a module. The following figure shows a high-level view of how an Angular application is composed:

Components are further divided into three main parts:

  • HTML, which forms the UI of the component called template. These UI templates form the view of the application. Templates have a 1:1 relationship with the component, and can be defined either inline or in a separate HTML file.
  • A class that is written in TypeScript and contains all the properties and methods that are required by the view. Properties are the data members that are bound to the view and used to display the data. Methods are action events that are performed from the view, such as a button click.
  • Angular needs a way to identify a class defined above as a component so that it can process it to display on the screen. This information is provided to Angular by the form of metadata.

The following is a graphical representation of a component:

This approach of having multiple components to form a module and multiple modules to form an application allows us to have separation of concerns and create multiple reusable components that can be used in different applications.

When we navigate to the URL of an Angular application, the first component that is loaded is always a root application component, and then the Angular router uses the routing configuration defined to match the component with the URL, and loads that component. The components template is then displayed in the browser, with data fetched from the server. A component can be made up of multiple smaller components, which are then loaded subsequently.

SNC – the architecture

Before we start developing our application, it is a good idea to look at the high-level architecture of what we will be building. The architecture provides us with the blueprint for designing our application, which in this case, will define the components that we will be building and their hierarchy. The following is an architecture diagram of SNC:

This application is comprised of the set of components and modules with index.html as our starting point. From index.html, we have an app component, which is the parent component. Then we have two components, namely header and footer, to provide with common content. Our main application is made of one component, news, which provides the primary user interface. We also have a service layer, which is used to make a backend call to fetch the top 10 news stories for a specific channel. The news component will show all the stories in a list format. This is achievable because of the hierarchical setup of components, with news as a parent component and story as a child component. In this chapter, we will keep it simple and develop only one component, which will have the list of stories; we will be adding components and their interaction in Chapter 3, Sports News Combinator - Adding Features, and Chapter 4, Sports News Combinator - the Final Version.

SNC – code setup

Angular provides multiple ways to set up the initial code structure, with options ranging from quick seed project, found at https://github.com/angular/quickstart, to Angular Command Line Interface (Angular CLI), which is an npm package and allows you to create applications that can run immediately. There are also multiple startup projects provided by various Angular enthusiasts, each with something different. Angular is a frontend framework that needs to be hosted on a server to run. It supports various servers such as node, IIS, and even Tomcat.

As we saw earlier, Angular is built with modules, with each module loading different components. Angular supports module loaders such as SystemJS and Webpack. You will find startup projects with either of the module loaders. For our application, we will use Angular CLI to create our initial project structure. We will look at Angular CLI and other startup projects in detail in Chapter 8, Trello – Using Angular CLI; here, just follow the steps we discuss and we should have our application running in no time.

If we had to manually set up a project from scratch, we would have to perform the following steps:

  1. First, we would need to create an application folder, a traditional app folder.
  2. Add package details and other configuration files.
  3. Install these packages using npm.
  4. Then we need to create an Angular root module. As we discussed in the SNC - architecture section, each application has one root module, which is required to load the application.
  1. Create a file called main.ts, which will load the module.
  2. Create an index.html file that will be our one and only fully HTML file.
  3. Develop your first component, which will be called from the app component.
  4. Define Angular routes to help Angular identify which component to load based on the URL request.

As you will notice, there are quite a few steps that need to be performed, and doing these manually is time-consuming and error-prone. This is where Angular CLI comes in. It creates all these files and also some boilerplate code for our first component. Angular CLI also provides commands to create new components/services/pipes/directives, among others. Angular CLI code comes with a built-in server from the Node that helps run the application in the development mode.

The Angular CLI package helps create an initial web application for Angular with Webpack and node server built in. It follows best practices as defined by the official Angular team, and helps to provide us with the correct folder structure to manage the code.

Angular CLI  setup

To start using Angular CLI, you will need to install the Angular CLI package from npm. npm, or Node Package Manager, is a package manager for all the client-side repositories. If you don't have npm and node on your machine, you can install it by downloading the executable from Node's website at https://nodejs.org/en/download/. If you think you already have node and npm, you can check which version you have with the following command executed in the Terminal window:

node -v
npm -v

These commands will give you the version you already have installed on your machine. Before Angular CLI can help you build web applications, you need to install Angular CLI itself from npm with the following command on a Terminal window:

npm install -g angular-cli

This command will install the angular-cli package in your global npm scope.

Application setup

Once we have CLI installed, then we can start creating our application. Creating an application with CLI is as simple as running the following command in your Terminal window:

ng new <<projectname>> 

The project name will be the name you would like to give to your project, which in our case, will be SportsNewsCombinator. The following screenshot shows the executed command and the result:

As you can see in the preceding screenshot, the CLI created a load of files and folders for our project. If you compare the files that we discussed in the previous section when listing down the manual steps to configure a new project, you will find all those here. In addition, there are files for e2e test cases, which we will not focus on at this time. As we discussed earlier, the CLI provides the built-in node server for us to run our application; the following command does that exactly:

ng serve

This command builds the projects and starts the web server. Once this command is executed, we can just navigate to our browser and open the URL http://localhost:4200.

You should see a page similar to the following:

And we are up and running. Though this is nowhere close to how our application will look, this step helps us to start our application.

SNC – folder structure

Angular CLI creates the folder structure, which is one of the recommended ones from the Angular team. Although you can create your own custom folder structure and follow the practices as per your organization, Angular CLI helps to get you started with minimal effort. The following screenshot shows the folder structure that was created for our project:

The following are the folders created by Angular CLI:

  • e2e: This folder is used for creating and managing end-to-end test cases for the application. In this example, we will not focus on writing test cases. We will cover how to write test cases later in the book.
  • node_modules: All the packages that we define in package.json are downloaded by npm under this folder. We never check-in this folder with our code base and always expect users to run npm install to download the packages. If you are downloading this code from GitHub, do remember to run the npm install command.
  • src: All our application code resides in this folder. We have an app folder inside the src, which will have all the application-related files and an assets folder, which will have all external assets such as icons and images.
  • environments: The purpose of this folder is to provide environmental configurations when you are building your application. You may have different configurations for different environments, and this folder helps you manage that.
  • Other files: We have other files in our src folder which are used at startup, such as main.ts, index.html, and tsconfig.app.json. We will look at these files when developing our application.

Now it's time to get our hands dirty.

 

Creating our model

Before we start building our first component, let's first create our model. A model is an entity that represents some logical data. Here, in our case, we will have two primary models, namely news and articles. The article model represents the articles that are fetched from the specific website, and the news model is the enclosing model of articles that will contain the array of articles.

In this chapter, we are not making a live web service call to fetch the articles, but will just hardcode the data to show the initial binding aspect of the application. But it is useful to understand the data format from the web service response so that we can identify the model structure that needs to be created. The following is one such response from NFL news:

{
"status": "ok",
"source": "nfl-news",
"sortBy": "top",
"articles": [
{
"author": "Lakisha Jackson",
"title": "Mike Williams denies report on season-
ending surgery"
,
"description": "Los Angeles Chargers first-round pick
Mike Williams is denying reports that he might need
season-ending back surgery. The rookie wideout
addressed the rumors during Alshon Jeffery's camp
on Saturday."
,
"url": "http://www.nfl.com/news/story/
0ap3000000821316/article/mike-williams-denies-
report-on-seasonending-surgery",
"urlToImage": "http://static.nfl.com/static/content/
public/photo/2017/07/22/
0ap3000000821315_thumbnail_200_150.jpg",
"publishedAt": "2017-07-22T23:21:00Z"
},
{
"author": "Jeremy Bergman",
"title": "Tamba Hali, upset with snaps, launches
tweetstorm"
,
"description": "We've got ourselves a Saturday
afternoon tweetstorm in late July, courtesy of
Chiefs pass rusher Tamba Hali. The veteran bemoaned
his lack of snaps in the Chiefs' playoff loss to
Pittsburgh."
,
"url": "http://www.nfl.com/news/story/
0ap3000000821309/article/
tamba-hali-upset-with-snaps-launches-tweetstorm",
"urlToImage": "http://static.nfl.com/static/content/
public/photo/2017/07/22/
0ap3000000821310_thumbnail_200_150.jpg",
"publishedAt": "2017-07-22T20:30:00Z"
}
]
}

As we can see, the JSON has two parts to it. The first part provides us with basic information about the web service call, such as status, source, and criterion with which we called the web service. The second part is the array of articles that are returned by the new website. The article array consists of article objects that have the following properties:

  • author
  • title
  • description
  • url
  • urlToImage
  • publishedAt

Under the src folder, add a new folder named models. This folder will contain all our models that will be required to manage data for our application. Once the folder is created, let's create our first file, article.ts.

The Article model looks like the following:

export class Article{
author:string;
title:string;
description: string;
url:string;
urlToImage:string;
publishedAt:Date;
}

Here, we created all the properties in the Article class we had identified in our web service response. All the properties are public in their scope as that is the default access modifier in TypeScript.

Next up is the news.ts file, which will be our parent model and will have an array of articles and status details. The following is the model that we created:

export class News {
status:string;
source:string;
sortBy:string;
articles: Article[];
}

Here, as we are referencing another file (article), we need to import that in our news class by writing the following code at the top of the news.ts file:

import {Article} from './Article';

This takes care of our models. Now let's create our first component.

 

First component – NewsComponent

Components are the building blocks of the Angular application. Each component represents some functionality of the application which, when combined with other components, provides a rich user experience. Angular components consist of four parts:

  • Template
  • Class, which is written in TypeScript
  • Metadata, which tells Angular about the class
  • Import statements, which provide reference to other components and services of the application

The following is a graphical representation of the composition of a component:

Template

The template provides the user interface of the component. It's created in HTML and details the elements that are represented in that component. The template for the component can be defined either inline, or in a separate file. We can create an inline template in two ways:

  • We can use a template property in the @Component decorator and define the HTML in single or double quotes. We will read about the @Component decorator in the next chapter. The following is a code example of an inline template:
template: "<h1>{{article.title}}</h1>"
  • If the HTML is more than a couple of lines long, then we can use ES2015 backticks to define the HTML in multiline. There is no difference between either of these ways, apart from readability. Defining inline templates with backticks allows us to create multiline strings, which are more readable:
template: `
<li>
<div>
{{article.description}}
</div>
</li>`

With our view and logic in one file, in one place, it helps to keep track of our bindings with the HTML properties. But, if our HTML is longer than a few lines, then the inline template may not provide many advantages. The inline template is a string, and hence we do not get any IntelliSense support for the HTML tags and syntax checking. The bigger our HTML, the more challenging it becomes to define inline templates.

In these cases, it's better to define the HTML in the separate HTML file and have it linked to the component using the templateUrl property. In the templateUrl property, we define the path of our HTML file, which is relative to index.html. The following is an example of the templateUrl property:

templateUrl: './news.component.html'

Component class

The component class is where the brain of the component resides. This class is written in TypeScript, and has properties and methods. The properties define the data members of the component, and are bound to the template using Angular binding syntax. The methods provide interface for the events that are triggered on the user interface.

As we have learned, each class is defined by the class keyword followed by the class name. One of the best practices defined for the component class is to name the class followed by the component keyword, such as newsComponent. The export keyword in front of the class allows the class to be available to the other components of the application. The following is an example of one such class:

export class itemComponent{
item: string;
itemCount: number;
constructor(){
console.log('Constructor called');
}
printItemDetail(){
console.log('${this.item} has total ${this.itemCount}
copies'
);
}
}

Metadata of the component

The definition of metadata is information about the data, which means when we provide details of the data we use, those details are called metadata. For Angular to understand that the class defined is a component, we need to provide metadata, which in this case would be the information to Angular informing it what the class is about. The metadata also provides Angular with details such as the template for that component, CSS styles for the HTML, and the selector that would be used to represent the component.

The metadata is defined using a decorator on top of the class. The decorator is a JavaScript concept that is proposed for ES7 and is implemented in TypeScript. You can identify the decorator by looking for the @ sign. The component decorator is defined by Angular and has options that allow providing details about the component. Some of the frequently used options are the following:

  • Template/templateUrl: As we discussed in the previous section, this property allows us to define the template for the component.
  • Selector: This defines the component's directive name; using this name, Angular identifies the HTML to be loaded.
  • StyleUrl: This property helps us to define the path of the CSS file for that component. As is the case with the template, we can define CSS either inline or in a separate file.

The following is a code sample for the metadata:

@Component({
s
elector: 'snc-news',
templateUrl: './news.component.html',
styleUrls: ['./news.component.css']
})

To refer to this component in any other HTML file, we will use the selector property as an HTML tag.

Import

In most cases, the components you are going to create will refer to some external function, or a class. This class can be another component, a model that defines the custom data type, or even a third-party library. To be able to access these functions, we need to import them in our component. Angular allows such imports by using the import keyword.

The import keyword is similar to the using statement we have in C# language. This helps us to access the external methods and properties. One import statement that you will have in your component class would be from Angular. We import the component keyword from the Angular core module, which is used as a decorator in our class. The following is the syntax of the import keyword:

import { Component, OnInit } from '@angular/core'

The import syntax requires that the members we need should be defined in curly braces, followed by the path of the module that contains that member. In the above case, we are importing component and OnInit members from Angular core module.

newsComponent

For our SNC application, we will be creating our first component named newsComponent. The purpose of this component will be to display the latest news from the news source. When we launch our application, this will be the main component that will be loaded. For this chapter, as we decided, we will just have a basic component with some hardcoded data, hence we will just add a few lines of news articles and display them on the user interface.

Angular CLI provides us with the command to generate components for our application. It not only generates the barebone class for the component, but also the external template, and adds the reference to the component in the app module. The syntax of generating a new component is as follows:

ng generate  component <<componentname>>

The following screenshot shows the command we execute for our newsComponent, which generates the required files. We will be creating our component in a dashboard folder under the app folder:

Here, we mentioned that our component is a news component under the dashboard folder, and Angular CLI created three files. Angular CLI creates a folder for the component with the component name, news in our case, to make sure we have separation of concern.

The flag spec false informs Angular CLI not to create the spec files for test cases. By default, Angular CLI, when generating the component or service or pipes, will create an additional file for writing test cases. We will be looking at how to write test cases in an Angular application in Chapter 8, Trello – Using Angular CLI.

You will have noticed here that there is an update to the app.module file as well. This file defines all the components that are under the app module. We will discuss modules in more detail in the following chapter; here, we just want to understand that each component that is created needs to be a reference in the module file. Angular uses this module file to identify which components are associated, and load them appropriately.

Now let's add some code in our newly created component.

newsComponent business logic

Our news component will be very simple and will have the following logic in it:

  1. We will first import the reference to our models, namely News and Article:
import {News} from '../../../models/news';
import {Article} from '../../../models/article';
  1. Then we will create an object of our News model inside the newComponent class:
latest_news: News = new News();

We will have a private method in our class, which will seed our news object. This method will just create some hardcoded objects, which we will display on the screen:

private seedNewsData(): News{
let news:News= new News();
news.status = "ok";
news.source="nfl";
news.sortBy="top";
news.articles = this.seedArcticles();
return news;
}
private seedArcticles():Article[]{
let articles:Article[] = new Array();
articles.push({
......
return articles;
}

This private method will be called from the ngOnInit method. The ngOnInit method is one of the life cycle hooks provided by Angular. The life cycle hooks are the methods that are exposed by the Angular for us to add logic to the component load and unload event. The ngOnInit method is exposed from the Angular core module, and in the following code snippet we see how to use this:

ngOnInit() {
this.latest_news = this.seedNewsData();
}
  1. Once we have assigned the news data to the new object, we can then bind this news property to the HTML template for the new component.

newsComponent template logic

You will have noticed that when we created the component from Angular CLI, it created a separate file for the template. We will be using this file to define our HTML for news details and bind the news property which we defined in the component to display the data.

As our news articles are a list, we will be using one of the built-in Angular structural directives, *ngFor. Angular has predefined directives called structural directives, which enable us to change the structure of the HTML at runtime based on the input provided. These directives add power and flexibility to our HTML by providing features such as for loops and if logic. Here, we are using ngFor to loop through our list of news articles and print each article as a separate element. The following is the code where we use ngFor on the news article:

 <li *ngFor="let article of latest_news.articles">

The preceding statement tells Angular to loop through all the articles in the news object and assign each article to the variable article defined after the let statement. This allows us to access the article properties by using the dot syntax.

Angular provides interpolation for binding the values of properties from the class to the HTML, by using the syntax of double curly braces {{}}. When Angular finds these double curly braces, it evaluates the expression inside these and displays the result as the value in an HTML element. For example, we have the following HTML in our newComponent file:

<div class="para">
{{article.description}}
</div>

Angular here evaluates the expression article.description and prints the result on the screen. You can find the whole HTML on the GitHub page.

Now, once we have defined our component and its respective HTML, it's time to run our application and see the output.

SNC – running the code

As we discussed before, Angular CLI provides a built-in server that builds the application and hosts it on the local node server. We can now run our application using the same command of npm serve. Once you run this command, navigate to http://localhost:4200 in your browser and it should present you with our first cut of the SNC website, as shown in the following screenshot:

 

Summary

In this chapter, our focus was to start with our first application and, in doing so, go through some of the features of TypeScript and Angular. We learned about data types in TypeScript, and the type inference feature of TypeScript, which allows TypeScript to identify the types implicitly for the variable defined. Then we looked at the classes provided in TypeScript and how TypeScript provides us with the object-oriented feature to help produce better code.

Our application is built with Angular and TypeScript, so it was necessary to have an understanding of Angular concepts, which was the next topic that we discussed. We looked at Angular architecture, and discovered what components are and how are they composed. We are building our application with Angular CLI, a command-line interface that provides the ability to create a barebone project with all the required configuration in place.

Then we started building our project by defining its high-level architecture and code setup. We looked at some concepts such as creating components and templates, and basic data binding, and used these components to create our first application component, newsComponent.

In this chapter, the focus was to build our basics, hence our newsComponent did not have much functionality. We just created static data and used that to display on the main page.

In the next chapter, we will continue our journey by adding features such as adding basic routing and data format to the SNC application. In doing so, we will focus on writing more object-oriented code using features such as interfaces in TypeScript. We will discuss classes in detail, with constructors, functions, and optional parameters. From the Angular perspective, we will delve deep into components, templates, and binding.

About the Author

  • Sachin Ohri

    Sachin Ohri is a Technology Architect with a keen interest in web-based technologies. He has been writing web applications for more than a decade, with technologies such as .NET, JavaScript, Durandal, Angular, and TypeScript.

    He works on providing technical solutions, including architectural design, technical support, and development expertise, to Fortune 500 companies.

    He considers himself a polygot developer willing to learn new languages and technology. Recently, he has been focusing on cloud-based web application development with Microsoft Azure. He holds various Microsoft certifications, such as Microsoft Azure Architect, Microsoft ASP.NET MVC web application, and Microsoft Programming with C#.

    Browse publications by this author

Latest Reviews

(4 reviews total)
Dobré knihy za výbornou cenu.
I've not had time yet to review this book. It seems that it will be OK.
Excellent service. Easily navigated from search to checkout.
TypeScript 2.x By Example
Unlock this book and the full library for FREE
Start free trial