Thursday, 3 May 2018

Angular Template Syntax - Interpolation

The Angular application manages what the user sees and can do, achieving this through the interaction of a component class instance (the component) and its user-facing template.

HTML in templates:
HTML is the language of the Angular template. Almost all HTML syntax is valid template syntax. The <script> element is a notable exception; it is forbidden, eliminating the risk of script injection attacks. In practice, <script> is ignored and a warning appears in the browser console.
Some legal HTML doesn't make much sense in a template. The <html><body>, and <base> elements have no useful role. Pretty much everything else is fair game.
You can extend the HTML vocabulary of your templates with components and directives that appear as new elements and attributes.

Interpolation ( {{...}} )
You met the double-curly braces of interpolation, {{ and }}, early in your Angular education.
src/app/app.component.html
<p>My current hero is {{currentHero.name}}</p>
You use interpolation to weave calculated strings into the text between HTML element tags and within attribute assignments.
src/app/app.component.html
<h3>
  {{title}}
  <img src="{{heroImageUrl}}" style="height:30px">
</h3>
The text between the braces is often the name of a component property. Angular replaces that name with the string value of the corresponding component property. In the example above, Angular evaluates the title and heroImageUrl properties and "fills in the blanks", first displaying a bold application title and then a heroic image.
More generally, the text between the braces is a template expression that Angular first evaluates and then converts to a string. The following interpolation illustrates the point by adding the two numbers:
src/app/app.component.html
<!-- "The sum of 1 + 1 is 2" -->
<p>The sum of 1 + 1 is {{1 + 1}}</p>
The expression can invoke methods of the host component such as getVal(), seen here:
src/app/app.component.html
<!-- "The sum of 1 + 1 is not 4" -->
<p>The sum of 1 + 1 is not {{1 + 1 + getVal()}}</p>
Angular evaluates all expressions in double curly braces, converts the expression results to strings, and links them with neighboring literal strings. Finally, it assigns this composite interpolated result to an element or directive property.

Template expressions:
A template expression produces a value. Angular executes the expression and assigns it to a property of a binding target; the target might be an HTML element, a component, or a directive.
The interpolation braces in {{1 + 1}} surround the template expression 1 + 1. In the property binding, a template expression appears in quotes to the right of the = symbol as in [property]="expression".
You write these template expressions in a language that looks like JavaScript. Many JavaScript expressions are legal template expressions, but not all.

Expression context:
The expression context is typically the component instance. In the following snippets, the title within double-curly braces and the isUnchanged in quotes refer to properties of the AppComponent.
src/app/app.component.html
{{title}}
<span [hidden]="isUnchanged">changed</span>
An expression may also refer to properties of the template's context such as a template input variable (let hero) or a template reference variable (#heroInput).
src/app/app.component.html
<div *ngFor="let hero of heroes">{{hero.name}}</div>
<input #heroInput> {{heroInput.value}}
The context for terms in an expression is a blend of the template variables, the directive's context object (if it has one), and the component's members. If you reference a name that belongs to more than one of these namespaces, the template variable name takes precedence, followed by a name in the directive's context, and, lastly, the component's member names.
The previous example presents such a name collision. The component has a hero property and the *ngFor defines a hero template variable. The hero in {{hero.name}} refers to the template input variable, not the component's property.

Statement context:
As with expressions, statements can refer only to what's in the statement context such as an event handling method of the component instance.
The statement context is typically the component instance.
The deleteHero in (click)="deleteHero()" is a method of the data-bound component.
src/app/app.component.html
<button (click)="deleteHero()">Delete hero</button>
The statement context may also refer to properties of the template's own context. In the following examples, the template $event object, a template input variable (let hero), and a template reference variable (#heroForm) are passed to an event handling method of the component.
src/app/app.component.html
<button (click)="onSave($event)">Save</button>
<button *ngFor="let hero of heroes" (click)="deleteHero(hero)">{{hero.name}}</button>
<form #heroForm (ngSubmit)="onSubmit(heroForm)"> ... </form>
Template context names take precedence over component context names. In deleteHero(hero) above, the hero is the template input variable, not the component's hero property.

Statement guidelines:
As with expressions, avoid writing complex template statements. A method call or simple property assignment should be the norm.


Binding syntax: An overview
Data binding is a mechanism for coordinating what users see, with application data values. While you could push values to and pull values from HTML, the application is easier to write, read, and maintain if you turn these chores over to a binding framework. You simply declare bindings between binding sources and target HTML elements and let the framework do the work.
Angular provides many kinds of data binding. This guide covers most of them, after a high-level view of Angular data binding and its syntax.
Binding types can be grouped into three categories distinguished by the direction of data flow: from the source-to-view, from view-to-source, and in the two-way sequence: view-to-source-to-view:
Data direction
Syntax
Type
One-way from data source to view target
{{expression}}
[target]="expression"
bind-target="expression"
Interpolation
Property
Attribute
Class
Style
One-way from view target to data source
(target)="statement"
on-target="statement"
Event
Two-way
[(target)]="expression"
bindon-target="expression"
Two-way
Binding types other than interpolation have a target name to the left of the equal sign, either surrounded by punctuation ([]()) or preceded by a prefix (bind-on-bindon-).
The target name is the name of a property. It may look like the name of an attribute but it never is to appreciate the difference, you must develop a new way to think about template HTML.

Binding targets:
The target of a data binding is something in the DOM. Depending on the binding type, the target can be an (element | component | directive) property, an (element | component | directive) event, or (rarely) an attribute name.
Type
Target
Examples
Property
Element property
Component property
Directive property
src/app/app.component.html
<img [src]="heroImageUrl">
<app-hero-detail [hero]="currentHero"></app-hero-detail>
<div [ngClass]="{'special': isSpecial}"></div>
Event
Element event
Component event
Directive event
src/app/app.component.html
<button (click)="onSave()">Save</button>
<app-hero-detail (deleteRequest)="deleteHero()"></app-hero-detail>
<div (myClick)="clicked=$event" clickable>click me</div>
Two-way
Event and property
src/app/app.component.html
<input [(ngModel)]="name">
Attribute
Attribute (the exception)
src/app/app.component.html
<button [attr.aria-label]="help">help</button>
Class
class property
src/app/app.component.html
<div [class.special]="isSpecial">Special</div>
Style
style property
src/app/app.component.html
<button [style.color]="isSpecial ? 'red' : 'green'">
Note: The brackets tell Angular to evaluate the template expression. If you omit the brackets, Angular treats the string as a constant and initializes the target property with that string. It does not evaluate the string!

One-time string initialization:
You should omit the brackets when all of the following are true:
  • The target property accepts a string value.
  • The string is a fixed value that you can bake into the template.
  • This initial value never changes.
You routinely initialize attributes this way in standard HTML, and it works just as well for directive and component property initialization. The following example initializes the prefix property of the HeroDetailComponent to a fixed string, not a template expression. Angular sets it and forgets about it.
src/app/app.component.html
<app-hero-detail prefix="You are my" [hero]="currentHero"></app-hero-detail>
The [hero] binding, on the other hand, remains a live binding to the component's currentHero property.

Property binding or interpolation?
You often have a choice between interpolation and property binding. The following binding pairs do the same thing:
src/app/app.component.html
<p><img src="{{heroImageUrl}}"> is the <i>interpolated</i> image.</p>
<p><img [src]="heroImageUrl"> is the <i>property bound</i> image.</p>

<p><span>"{{title}}" is the <i>interpolated</i> title.</span></p>
<p>"<span [innerHTML]="title"></span>" is the <i>property bound</i> title.</p>
Interpolation is a convenient alternative to property binding in many cases.
When rendering data values as strings, there is no technical reason to prefer one form to the other. You lean toward readability, which tends to favor interpolation. You suggest establishing coding style rules and choosing the form that both conforms to the rules and feels most natural for the task at hand.
When setting an element property to a non-string data value, you must use property binding.
Content security: Imagine the following malicious content.
src/app/app.component.ts
evilTitle = 'Template <script>alert("evil never sleeps")</script>Syntax';
Fortunately, Angular data binding is on alert for dangerous HTML. It sanitizes the values before displaying them. It will not allow HTML with script tags to leak into the browser, neither with interpolation nor property binding.
src/app/app.component.html
<!--
  Angular generates warnings for these two lines as it sanitizes them
  WARNING: sanitizing HTML stripped some content (see  http://g.co/ng/security#xss).
 -->
<p><span>"{{evilTitle}}" is the <i>interpolated</i> evil title.</span></p>
<p>"<span [innerHTML]="evilTitle"></span>" is the <i>property bound</i> evil title.</p>
Interpolation handles the script tags differently than property binding but both approaches render the content harmlessly.






No comments:

Post a Comment