In-depth Guides
Template Syntax

Understanding binding

In an Angular template, a binding creates a live connection between a part of the UI created from a template (a DOM element, directive, or component) and the model (the component instance to which the template belongs). This connection can be used to synchronize the view with the model, to notify the model when an event or user action takes place in the view, or both. Angular's Change Detection algorithm is responsible for keeping the view and the model in sync.

Examples of binding include:

  • text interpolations
  • property binding
  • event binding
  • two-way binding

Bindings always have two parts: a target which will receive the bound value, and a template expression which produces a value from the model.

Syntax

Template expressions are similar to JavaScript expressions. Many JavaScript expressions are legal template expressions, with the following exceptions.

You can't use JavaScript expressions that have or promote side effects, including:

  • Assignments (=, +=, -=, ...)
  • Operators such as new, typeof, or instanceof
  • Chaining expressions with ; or ,
  • The increment and decrement operators ++ and --
  • Some of the ES2015+ operators

Other notable differences from JavaScript syntax include:

  • No support for the bitwise operators such as | and &

Expression context

Interpolated expressions have a context—a particular part of the application to which the expression belongs. Typically, this context is the component instance.

In the following snippet, the expression recommended and the expression itemImageUrl2 refer to properties of the AppComponent.

src/app/app.component.html

      
<div>
<h1>Interpolation and Template Expressions</h1>
<hr />
<div>
<h2>Interpolation</h2>
<h3>Current customer: {{ currentCustomer }}</h3>
<p>{{ title }}</p>
<div><img alt="item" src="{{ itemImageUrl }}"></div>
<h3>Evaluating template expressions </h3>
<h4>Simple evaluation (to a string):</h4>
<!-- "The sum of 1 + 1 is 2" -->
<p>The sum of 1 + 1 is {{ 1 + 1 }}.</p>
<h4>Evaluates using a method (also evaluates to a string):</h4>
<!-- "The sum of 1 + 1 is not 4" -->
<p>The sum of 1 + 1 is not {{ 1 + 1 + getVal() }}.</p>
</div>
<hr />
<h2>Expression Context</h2>
<div>
<h3>Component context, properties of app.component.ts:</h3>
<h4>{{ recommended }}</h4>
<img alt="item 2" [src]="itemImageUrl2">
</div>
<div>
<h4>Template context, template input variables (let customer):</h4>
<ul>
@for (customer of customers; track customer) {
<li>{{ customer.name }}</li>
}
</ul>
</div>
<div (keyup)="0">
<h4>Template context: template reference variables (#customerInput):</h4>
<label for="customer-input">Type something:
<input id="customer-input" #customerInput>{{ customerInput.value }}
</label>
</div>
</div>

An expression can also refer to properties of the template's context such as a template input variable or a template reference variable.

The following example uses a template input variable of customer.

src/app/app.component.html (template input variable)

      
<div>
<h1>Interpolation and Template Expressions</h1>
<hr />
<div>
<h2>Interpolation</h2>
<h3>Current customer: {{ currentCustomer }}</h3>
<p>{{ title }}</p>
<div><img alt="item" src="{{ itemImageUrl }}"></div>
<h3>Evaluating template expressions </h3>
<h4>Simple evaluation (to a string):</h4>
<!-- "The sum of 1 + 1 is 2" -->
<p>The sum of 1 + 1 is {{ 1 + 1 }}.</p>
<h4>Evaluates using a method (also evaluates to a string):</h4>
<!-- "The sum of 1 + 1 is not 4" -->
<p>The sum of 1 + 1 is not {{ 1 + 1 + getVal() }}.</p>
</div>
<hr />
<h2>Expression Context</h2>
<div>
<h3>Component context, properties of app.component.ts:</h3>
<h4>{{ recommended }}</h4>
<img alt="item 2" [src]="itemImageUrl2">
</div>
<div>
<h4>Template context, template input variables (let customer):</h4>
<ul>
@for (customer of customers; track customer) {
<li>{{ customer.name }}</li>
}
</ul>
</div>
<div (keyup)="0">
<h4>Template context: template reference variables (#customerInput):</h4>
<label for="customer-input">Type something:
<input id="customer-input" #customerInput>{{ customerInput.value }}
</label>
</div>
</div>

This next example features a template reference variable, #customerInput.

src/app/app.component.html (template reference variable)

      
<div>
<h1>Interpolation and Template Expressions</h1>
<hr />
<div>
<h2>Interpolation</h2>
<h3>Current customer: {{ currentCustomer }}</h3>
<p>{{ title }}</p>
<div><img alt="item" src="{{ itemImageUrl }}"></div>
<h3>Evaluating template expressions </h3>
<h4>Simple evaluation (to a string):</h4>
<!-- "The sum of 1 + 1 is 2" -->
<p>The sum of 1 + 1 is {{ 1 + 1 }}.</p>
<h4>Evaluates using a method (also evaluates to a string):</h4>
<!-- "The sum of 1 + 1 is not 4" -->
<p>The sum of 1 + 1 is not {{ 1 + 1 + getVal() }}.</p>
</div>
<hr />
<h2>Expression Context</h2>
<div>
<h3>Component context, properties of app.component.ts:</h3>
<h4>{{ recommended }}</h4>
<img alt="item 2" [src]="itemImageUrl2">
</div>
<div>
<h4>Template context, template input variables (let customer):</h4>
<ul>
@for (customer of customers; track customer) {
<li>{{ customer.name }}</li>
}
</ul>
</div>
<div (keyup)="0">
<h4>Template context: template reference variables (#customerInput):</h4>
<label for="customer-input">Type something:
<input id="customer-input" #customerInput>{{ customerInput.value }}
</label>
</div>
</div>

HELPFUL: Template expressions cannot refer to anything in the global namespace, except undefined. They can't refer to window or document. Additionally, they can't call console.log() or Math.max() and are restricted to referencing members of the expression context.

Preventing name collisions

The context against which an expression evaluates is the union 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, Angular applies the following precedence logic to determine the context:

  1. The template variable name.
  2. A name in the directive's context.
  3. The component's member names.

To avoid variables shadowing variables in another context, keep variable names unique. In the following example, the AppComponent template greets the customer, Padma.

The @for then lists each customer in the customers array.

src/app/app.component.ts

      
import {Component} from '@angular/core';
import {NgFor} from '@angular/common';
@Component({
standalone: true,
template: `
<div>
<!-- Hello, Padma -->
<h1>Hello, {{customer}}</h1>
<ul>
<!-- Ebony and Chiho in a list-->
@for (customer of customers; track customer) {
<li>{{ customer.value }}</li>
}
</ul>
</div>
`,
})
export class AppComponent {
customers = [{value: 'Ebony'}, {value: 'Chiho'}];
customer = 'Padma';
}

The customer within the @for is in the context of the implicit <ng-template> defined by the @for. It refers to each customer in the customers array and displays "Ebony" and "Chiho". "Padma" is not displayed because that name is not in that array.

On the other hand, the <h1> displays "Padma" which is bound to the value of the customer property in the component class.

Expression best practices

When using a template expression, follow these best practices:

  • Use short expressions

Use property names or method calls whenever possible. Keep application and business logic in the component, where it is accessible to develop and test.

  • Quick execution

Angular executes a template expression after every change detection cycle. Many asynchronous activities trigger change detection cycles, such as promise resolutions, HTTP results, timer events, key presses, and mouse moves.

An expression should finish quickly to keep the user experience as efficient as possible, especially on slower devices. Consider caching values when their computation requires greater resources.

No visible side effects

According to Angular's unidirectional data flow model, a template expression should not change any application state other than the value of the target property. Reading a component value should not change some other displayed value. The view should be stable throughout a single rendering pass.

An idempotent expression 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 if you call it twice consecutively. If the expression returns an object, including an array, it returns the same object reference if you call it twice consecutively.

What's next