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.
Table of Contents
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.

