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.
You may be familiar with the component/template duality from your experience with model-view-controller (MVC) or model-view-viewmodel (MVVM). In Angular, the component plays the part of the controller/viewmodel, and the template represents the view.
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. In the following sections, you’ll learn how to get and set DOM (Document Object Model) values dynamically through data binding.
Begin with the first form of data binding—interpolation—to see how much richer template HTML can be.
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.
You appear to be inserting the result between element tags and assigning it to attributes. It’s convenient to think so, and you rarely suffer for this mistake. Though this is not exactly true. Interpolation is a special syntax that Angular converts into a property binding. But first, let’s take a closer look at template expressions and statements.
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 section below, 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.
JavaScript expressions that have or promote side effects are prohibited, including:
- assignments (=, +=, -=, …)
- new
- chaining expressions with ; or ,
- increment and decrement operators (++ and –)
Other notable differences from JavaScript syntax include:
- no support for the bitwise operators | and &
- new template expression operators, such as |, ?. and !.
Expression context
The expression context is typically the component instance. In the following snippets, the title within double-curly braces and the is Unchanged 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.
Template expressions cannot refer to anything in the global namespace (except undefined). They can’t refer to window or document. They can’t call console.log or Math.max. They are restricted to referencing members of the expression context.
Expression guidelines
Template expressions can make or break an application. Please follow these guidelines:
- No visible side effects – A template expression should not change any application state other than the value of the target property. This rule is essential to Angular’s “unidirectional data flow” policy. You should never worry that reading a component value might change some other displayed value. The view should be stable throughout a single rendering pass.
- Quick execution – Angular executes template expressions after every change detection cycle. Change detection cycles are triggered by many asynchronous activities such as promise resolutions, http results, timer events, keypresses and mouse moves. Expressions should finish quickly or the user experience may drag, especially on slower devices. Consider caching values when their computation is expensive.
- Simplicity – Although it’s possible to write quite complex template expressions, you should avoid them. A property name or method call should be the norm. An occasional Boolean negation (!) is OK. Otherwise, confine application and business logic to the component itself, where it will be easier to develop and test.
- Idempotence – An idempotent expression is ideal because it is free of side effects and improves Angular’s change detection performance. In Angular terms, an idempotent expression always returns exactly the same thing until one of its dependent values changes.
Dependent values should not change during a single turn of the event loop. If an idempotent expression returns a string or a number, it returns the same string or number when called twice in a row. If the expression returns an object (including an array), it returns the same object reference when called twice in a row.