Quick answer: Angular data binding works in four directions. Interpolation {{ value }} prints data, property binding [property]="value" sets an element property, event binding (event)="handler()" listens for user actions, and two-way binding [(ngModel)] keeps an input and a variable in sync. Signals make all four update automatically.

Angular data binding: interpolation

Double braces print a value into the template. The expression inside is TypeScript, but keep it simple — if it needs several steps, compute it in the class.

<h2>{{ product.name }}</h2>
<p>{{ price() | currency }}</p>
<p>{{ items().length }} items</p>

Note price() with parentheses and items() too — those are signals, so you call them to read the current value. A plain property such as product.name is written without parentheses.

Property binding: setting values

Square brackets bind a component property to an element or child-component property. This is how you pass data down the tree.

<img [src]="imageUrl" [alt]="product.name" />
<button [disabled]="saving()">Save</button>
<app-card [product]="selected()" />

Use the property name, not the attribute name. [disabled] and [src] set the live DOM properties, which behave correctly for booleans and updates, unlike writing the raw attribute.

Event binding: listening for actions

Parentheses bind a template event to a method in the class. The special $event variable carries the browser event object.

<input (input)="onSearch($event)" />
<button (click)="addToCart()">Add</button>
<form (ngSubmit)="save()">...</form>

You can chain bindings on one element and mix them freely: [value] to push data in, (input) to pull it out.

Two-way binding with ngModel

Forms inputs are the one place where both directions are needed at once. The “banana in a box” syntax [(ngModel)] is shorthand for a property binding plus an event binding.

import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';

@Component({
  selector: 'app-search',
  imports: [FormsModule],
  template: `
    <input [(ngModel)]="term" placeholder="Search" />
    <p>Searching for: {{ term }}</p>
  `,
})
export class SearchComponent {
  term = '';
}

[(ngModel)] requires importing FormsModule in the component. Typing in the box updates term; setting term in code updates the box. That two-way loop is what makes template-driven forms readable, which we cover in the forms guide.

Control flow in the template

Angular 17 added built-in control flow, and it is now the way to branch and loop in templates. The old *ngIf and *ngFor directives are deprecated.

@if (user(); as u) {
  <p>Welcome, {{ u.name }}</p>
} @else {
  <a routerLink="/login">Sign in</a>
}

@for (item of items(); track item.id) {
  <li>{{ item.name }}</li>
} @empty {
  <li>No items yet.</li>
}

Two details matter. First, track is required on @for — give it a stable unique key such as item.id so Angular reuses DOM nodes instead of rebuilding them. Second, no imports are needed: @if and @for are part of the template language itself.

Template reference variables in Angular data binding

A hash name gives you a handle on an element to use elsewhere in the same template, without touching the class.

<input #email type="email" />
<button (click)="send(email.value)">Subscribe</button>

Reference variables are handy for small interactions and are how you read an uncontrolled input value directly in the template.

Next: component interaction, where these bindings connect parent and child. To learn template syntax with real screens, Ampersand Academy teaches Angular one-to-one.

Frequently asked questions

What is the difference between interpolation and property binding?

Interpolation prints a value as text between tags, as in {{ name }}. Property binding sets a DOM or component property, as in [disabled]=saving. Use interpolation for text and property binding for properties.

Why is track required in Angular @for?

track tells Angular how to identify each item so it can reuse DOM nodes when the list changes. Use a stable unique key such as item.id. Without a good key, Angular rebuilds rows and loses state.

Is ngIf still used in Angular?

It works but is deprecated. New code should use the @if, @for and @switch control flow syntax, which is part of the template language and needs no imports.

Do I need FormsModule for ngModel?

Yes. Two-way binding with ngModel requires importing FormsModule in the component that uses it, because ngModel is provided by that module.

What does the banana in a box syntax mean?

[(ngModel)] is shorthand that combines a property binding and an event binding, so the value flows both ways between the input and the variable.

Last updated on · Written by