When writing an application component in TypeScript, there are several new paradigms that you must become familiar and comfortable with. Though possibly intimidating initially, you will find that you'll be able to carry over much of your comprehension of Angular 1 directives.
The code and a live example of this are available at .
One of the simplest imaginable components we can build is a template element that interpolates some values into its template. In Angular 1, one way this could be achieved was by creating an element directive, attaching some data to the scope inside the link function, and a template that would reference the data. I selected this description specifically because nearly all those concepts have been binned.
Suppose you want to create a simple article component with a pseudo template as follows:
<p>{{date}}</p> <h1>{{title}}</h1> <h3>Written by: {{author}}</h3>
You want to create a component that will live inside its own HTML tag, render the template, and interpolate the values.
The elemental building block of Angular 2 applications is the component. This component could generally be defined with two pieces: the core class definition and the class decoration.
All Angular 2 components begin as a class. This class is used to instantiate the component, and any data required inside the component template will be accessible from the class's properties. Thus, the foundational class for the component would appear as follows:
[app/article.component.ts] export class ArticleComponent { currentDate:date; title:string; author:string; constructor() { this.currentDate = new Date(); this.title = ` Flight Security Restrictions to Include Insults, Mean Faces `; this.author = 'Jake'; } };
Here are a few things to note for those who are new to TypeScript or ES6 in general:
export
keyword. This is adherence to the new ES6 module convention, which naturally is also part of TypeScript. Assuming the Article
class is defined in the foo.ts
file, it can be imported to a different module using the import
keyword, and the path to that module would be import {Article} from './foo';
(this assumes that the importing file is in the same directory as foo.ts
).``
) instead of the traditional set of quotes (''
). You will find you become quite fond of this, as it means the '' + '' + ''
messiness formerly used to define multiline templates would no longer be necessary.propertyName:propertyType = optionalInitValue
. JavaScript is, of course, a loosely typed language, and JavaScript is what the browser is interpreting in this case. However, writing your application in TypeScript allows you to utilize type safety at compile time, which will allow you to avoid undesirable and unanticipated behavior.constructor()
method, which is invoked upon instantiation. Here, you are using the constructor to instantiate the properties of the class, which is a perfectly fine strategy for member initialization. Having the member property definition outside the constructor is allowed, since it is useful for adding types to properties; thus, here you are simply obviating the use of the constructor since you are able to add a type and assign the value in the same line. A more succinct style could be as follows:[app/article.component.ts] export class ArticleComponent { currentDate:date = new Date(); title:string = ` Flight Security Restrictions to Include Insults, Mean Faces `; author:string = 'Jake'; }
Although you have created a class that has information associated with it, it does not yet have any way to interface with the DOM. Furthermore, this class is yet to be assigned with any meaning in the context of Angular 2. You can accomplish this with decorators.
Decorators are a feature of TypeScript but not by any means unique to the language. Python developers, among many others, should be quite familiar with the concept of class modulation via explicit decoration. Generally speaking, it allows you to have a regularized modification of the defined classes using separately defined decorators. However, in Angular 2, you will largely be utilizing the decorators provided to you by the framework to declare the various framework elements. Decorators such as @Component
are defined in the Angular source code as a Component
function, and the function is applied as a decorator using the @
symbol.
An @
prefix signals that the imported function should be applied as a decorator. These decorators are visually obvious but will usually not exist by themselves or with an empty object literal. This is because Angular 2 decorators are generally made useful by their decorator metadata. This concept can be made more concrete here by using the predefined Component
decorator.
Nothing is available for free in Angular 2. In order to use the component decorator, it must be imported from the Angular 2 core
module into the module that wishes to use it. You can then prepend this Component
to the class definition:
[app/article.component.ts] import {Component} from '@angular/core'; @Component({}) export class ArticleComponent { currentDate:date = new Date(); title:string = ` Flight Security Restrictions to Include Insults, Mean Faces `; author:string = 'Jake'; }
As mentioned before, the @Component
decorator accepts a ComponentMetadata
object, which in the preceding code is just an empty object literal (note that the preceding code will not compile). Conceptually, this metadata object is very similar to the directive definition object in Angular 1. Here, you want to provide the decorator metadata object with two properties, namely selector
and template
:
[app/article.component.ts] import {Component} from '@angular/core'; @Component({ selector: 'article', template: ` <p>{{currentDate|date}}</p> <h1>{{title}}</h1> <h3>Written by: {{author}}</h3> ` }) export class ArticleComponent { currentDate:date = new Date(); title:string = ` Flight Security Restrictions to Include Insults, Mean Faces `; author:string = 'Jake'; }
Note that selector
is the string that will be used to find where the component should be inserted in the DOM, and template
is obviously the stringified HTML template.
With all this, you will be able to see your article component in action with the <article></article>
tag.
The class definition has supplanted the Angular 1 concept of having a controller. The component instances of this class have member properties that can be interpolated and bound into the template, similar to $scope
in Angular 1.
In the template, the interpolation and data binding processes seem to occur much in the same way, they did in Angular 1. This is not actually the case, which is visited in greater detail later in this chapter. The built-in date
modifier, which resembles an Angular 1 filter, is now dubbed with a pipe
although it works in a very similar fashion.
The selector
metadata property is a string representing a CSS selector. In this definition, you target all the occurrences of an article
tag, but the selector specificity and detail is of course able to handle a great deal of additional complexity. Use this to your advantage.
The concept that must be internalized for Angular 2 neophytes is the total encapsulation of a component. This book will go into further detail about the different abilities of the ComponentMetadata
object, but the paradigm they and all class decorators introduce is the concept that Angular 2 components are self-describing. By examining the class definition, you can wholly reason the data, service, class, and injectable dependencies. In Angular 1, this was not possible because of the "scope soup" pattern.
One could argue that in Angular 1, CSS styling was a second-class citizen. This is no longer the case with components, as the metadata object offers robust support for complex styling. For example, to italicize the author in your Article
component, use this code:
[app/article.component.ts] import {Component} from '@angular/core'; @Component({ selector: 'article', template: ` <p>{{currentDate|date}}</p> <h1>{{title}}</h1> <h3>Written by: {{author}}</h3> `, styles: [` h3 { font-style: italic; } `] }) export class ArticleComponent { currentDate:date = new Date(); title:string = ` Flight Security Restrictions to Include Insults, Mean Faces `; author:string = 'Jake'; }
Angular 2 will use this styles
property and compile it into a generated style sheet, which it will then apply to only this component. You do not have to worry about the rest of the HTML h3
tags being inadvertently styled. This is because Angular 2's generated style sheet will ensure that only this component—and its children—are subject to the CSS rules listed in the metadata object.
This is intended to emulate the total modularity of web components. However, since web components do not yet have universal support, Angular 2's design essentially performs a polyfill for this behavior.