Книга: Angular 2 Cookbook
Назад: 2. Conquering Components and Directives
Дальше: Passing members from a parent component into a child component

Using decorators to build and style a simple component

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.

Note

The code and a live example of this are available at .

Getting ready

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.

How to do it...

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.

Writing the class definition

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:

  • You will note the class definition is prefixed with an 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).
  • The title definition uses the new ES6 template string syntax, a pair of backticks (``) 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.
  • All the properties of this class are typed. TypeScript's typing syntax takes the form of 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.
  • All ES6 classes come with a predefined 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';           }   
  • The TypeScript compiler will automatically move the member initialization process inside the class constructor, so this version and the previous one are behaviorally identical.

Writing the component class decorator

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.

Note

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.

How it works...

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.

There's more...

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.

Note

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.

See also

  • Passing members from a parent component into a child component goes through the basics of downward data flow between components
  • Using ngFor and ngIf structural directives for model-based DOM control instructs you on how to utilize some of Angular 2's core built-in directives
  • Utilizing component lifecycle hooks gives an example of how you can integrate with Angular 2's component rendering flow
Назад: 2. Conquering Components and Directives
Дальше: Passing members from a parent component into a child component

thank you
Flame
cant read the code since it is all on a single line. Also this comments section is russian
Rakuneque
DATA COLLECTION AND ANALYSIS Two reviewers extracted data and assessed methodological quality independently lasix torsemide conversion Many others were in that space already