Developers Club geek daily blog

1 year, 10 months ago
We deal with syntax of templates in Angular2
Many having for the first time seen syntax of the Angular2 templates begin to lament, what horror made a pier, really it was impossible as in Angular1 at least. Why it was necessary to enter this variety skobochek, asterisks and other nonsense! However on closer examination all becomes far simpler, the main thing not to be frightened.

As templates in AngularJS are its integral part, it is important to deal with them at the very beginning of acquaintance from the new version of this framework. At the same time we will discuss what benefits this syntax in comparison with angular 1.x gives us. And it will be best of all to consider it on small examples.

This article is in many respects based on materials of these two articles:



To simplify material supply, let's understand. I will mean all branch of Angular 1.x while under Angular2 — a branch 2.x by AngularJS.

Note: evening of the day off therefore, etc. report about typographical errors in a pm. He is very grateful also pleasant reading.


Binding of properties of elements


In case of a simple data output of a difference you will not feel, however, if you decide to give a part of the fortune as value any attributes of elements, it is possible to observe interesting solutions already.

Let's refresh in memory as binding work for attributes in AngularJS. For this purpose we usually directly forwarded the expressions (interpolated at compilation of a template) directly in attribute of an element, or used one of a set of directives. For example ngValue for property parameter setting value at input.

Let's give an example as it works in AngularJS:

<input ng-value="expression" />

Also we do not forget that we can just interpolate result of expression directly as argument value:

<input value="{{expression}}" />

Let's notice interesting feature. The second option many avoid it as it is possible to see an intermediate status before angular interpolates values. However the first option uses directives. That is in order that at us everything was good, beautiful and convenient, we should make according to the directive on each property of all elements. Agree, not too that is convenient. Why not to add any designation for attribute which would tell an angulyara to zamepit value on it. And it would be quite good that syntax would be valid. And they added, now for this purpose it is necessary to envelop only the attribute (any attribute) interesting us in square brackets — [].

<input [value]="valueExpression" [placeholder]="placeholderExpression" />

However, we still have an opportunity to mepit the interpolated value, just as it was in AngularJS:

<input value="{{ valueExpression }}" placeholder="{{ placeholderExpression }}" />

Events


In AngularJS we could subscribe for events of elements using special directives. As well as in a case with properties, we should deal with the whole heap of possible events. And on each event it was necessary to do the directive. Perhaps, the most popular of such directives is ngClick:

<button ng-click="doSomething($event)">

Considering that we already solved such problem for properties of elements, probably it is worth solving also this problem? It was also made! To subscribe for an event, it is enough to register attribute ispolzuyuya the following syntax: (eventName). Thus we have an opportunity to subscribe for any event generated by our element at the same time without need to write the separate directive:

<button (click)="doSomething($event)">

Bilateral binding


There is a popular belief that a bilateral binding it is bad and that it is the main sin of an angulyar. It not absolutely so. The problem with a bilateral binding in AnugularJS was that it is used everywhere, without giving to developers of alternative (perhaps the situation with it will shortly change).

Nevertheless sometimes there are cases when the bilateral binding fine simplifies development, especially in case of forms. As it is implemented in Angular2? Let's think how to organize a bilateral binding having a one-sided binding svoyst elements and a binding of events:

<input type="text" [value]="firstName" (input)="firstName=$event.target.value" />

Besides, not really that is convenient. Therefore in Angular2 there is also a syntax sugar with use ngModel. The result will be identical to what we stated above:

<input type="text" [(ngModel)]="firstName" />

Local variables


For data transmission between elements within one template local variables are used. As the closest analogy in AngularJS, perhaps, it is possible to consider access to form elements by name through ngForm. Of course, it not absolutely correct comparison as it works only at the expense of the directive ngForm. In Angular2 you can use the reference to any object or a DOM element within an element of a template and its descendants, using local variables #.

<video #movieplayer ...>
  <button (click)="movieplayer.play()">
</video>

In this example we can see, how through a variable movieplayer we can get access to API of media of an element directly in a template.

In addition to the character #, you can also declare variables using a prefix var-. In this case instead of #movieplayer we could write var-movieplayer.

Asterisk (character *)


Character * raises most of all questions. Let's understand why it was necessary. For understanding of the reasons of adding of this character, we should remember such element as template.

Element template allows us to declare a piece of DOM which we can initialize later that gives us higher performance and more rational use of resources. Something it is similar on documentFragment in the context of HTML.

Perhaps, it will be simpler to show why it is necessary on an example:

<div style="display:none">
  <img src="path/to/your/image.png" />
</div>

In this small example we can see that the block is hidden (display:none). However the browser will try to load all the same the picture even if it is not required. If there is a lot of similar things on the page, it can have pernicious effect on the overall performance of the page.

Use of an element will become a solution of this problem template.

<template>
  <img src="path/to/your/image.png" />
</template>

In this case the browser will not load the image while we do not initialize a template.

But we will return to our rams. Use of the character * before the directive of an element will allow an angulyar to envelop at compilation an element in a template. It is simpler to look on an example:

<hero-detail *ngIf="isActive" [hero]="currentHero"></hero-detail>

This template will be transformed to such:

<template [ngIf]="isActive">
  <hero-detail [hero]="currentHero"></hero-detail>
</template>

Now it has to become clear that this character provides syntax sugar for achievement of higher performance when using conditional directives it seems ngFor, ngIf and ngSwitch. It is logical that there is no need in creation of a copy of a component hero-detail so far isActive is not truth.

Paypa


Paypa are a direct analog of filters from AngularJS. In general syntax of their application not especially exchanged:

<p>My birthday is {{ birthday | date:"MM/dd/yy" }} </p>

Why it was required to change the name from already usual filters for new paypa — a single question. It was made to emphasize new mechanics of operation of filters. Now it is not synchronous filters, but asynchronous paypa (by analogy with unix pipes).

In AngularJS filters are started synchronously for each $digest a cycle. It is demanded by the change tracking mechanism in AngularJs. In Angular2 change tracking considers dependences of data, therefore it allows to optimize a number of concepts. Also there was separation into stateful and stateless of a paypa (while AngularJS filra obviously were considered as stateful).

Paypa Stateless as it can be clear from the name, have no own status. These are pure functions. They are executed only once (or if the entering data changed). The majority of payp in Angular2 are paypama stateless. It allows to increase performance significantly.

Paypa Stateful opposite, have the status and they are executed often because the internal state can exchange. An example of a similar payp is Async. He receives on an input promis, subscribes for changes and returns zaresolvlenny value.

// это не TypeScript, это babel со stage-1, ну так, к сведенью
@Component({
  selector: 'my-hero',
  template: 'Message: {{delayedMessage | async}}',
})
class MyHeroAsyncMessageComponent {
  delayedMessage = new Promise((resolve, reject) => {
    setTimeout(() => resolve('You are my Hero!'), 500);
  });
}
// повелись? Неее, это просто TypeScript без определения типов.

In this example component my-hero will display Message: You are my Hero! only after but zaresolvlen promis delayedMessage.

To make paypa stateful we have to declare obviously it in metadata of it. Angular2 will think its stateless differently.

Elvis operator


In AngularJS we could do appeals to anything absolutely without serious consequences that quite often poured out in very artful bugs and complicated debugging. In Angular2 we will receive at last errors! However the similar solution can please not all without additional sugar.

In Javascript we quite often should check existence of any properties. Think all of us wrote something similar:

if (cordova &&cordova.plugins &&cordova.plugins.notification){
  // use cordova.plugins.notification
}

Doing such checks we of course want to avoid similar:

TypeError: Cannot read property 'notification' of undefined.

Elvis the operator was entered into coffescript for a solution of this problem. In Angular2 solved this problem using the same operator, but at the level of templates:

<p>Employer: {{employer?.companyName}}</p>

This record means that property employer optionally, and if it has empty value, then other part of expression is ignored. If we did not use this operator, then in this situation we would receive TypeError.

As well as in coffescript this operator it is possible to use some time within one expression, for example so: a?.b?.c?.d

Outputs


The Angular2 developers did huge work to make syntax of templates more flexible and powerful. Yes, some things demand a little time for adaptation, but in general over time all this seems more than natural. And, above all, not so everything is terrible as it seems at first sight.

This article is a translation of the original post at habrahabr.ru/post/274743/
If you have any questions regarding the material covered in the article above, please, contact the original author of the post.
If you have any complaints about this article or you want this article to be deleted, please, drop an email here: sysmagazine.com@gmail.com.

We believe that the knowledge, which is available at the most popular Russian IT blog habrahabr.ru, should be accessed by everyone, even though it is poorly translated.
Shared knowledge makes the world better.
Best wishes.

comments powered by Disqus