Angular Data Binding
Data binding connects a component's TypeScript state to its HTML template in either direction, and Angular gives you four distinct syntaxes for it.
Four Kinds of Binding
Angular binding syntax always tells you the direction of data flow just by looking at the punctuation. Curly braces read component state into text. Square brackets push a component value onto an element property. Parentheses pull an event from the DOM back into the component. Combining both brackets and parentheses gives you two-way binding.
Interpolation
Interpolation embeds a component expression directly into the text content of a template using double curly braces. Angular evaluates the expression, converts the result to a string, and re-renders it automatically whenever the underlying value changes.
Interpolation in a template
import { Component } from '@angular/core';
import { DecimalPipe } from '@angular/common';
import { bootstrapApplication } from '@angular/platform-browser';
@Component({
selector: 'app-price-tag',
standalone: true,
imports: [DecimalPipe],
template: `
<p>{{ productName }} costs {{ price | number:'1.2-2' }} dollars</p>
<p>In stock: {{ inStock ? 'yes' : 'no' }}</p>
`
})
export class PriceTagComponent {
productName = 'Wireless Mouse';
price = 24.5;
inStock = true;
}
bootstrapApplication(PriceTagComponent).catch(err => console.error(err));Property Binding
Property binding sets a DOM property, not an HTML attribute, which is why it can accept any TypeScript expression rather than only strings. Use square brackets around the target property name and assign it a component expression.
Property binding on standard and custom properties
import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
@Component({
selector: 'app-avatar',
standalone: true,
template: `
<img [src]="avatarUrl" [alt]="userName" [class.offline]="!isOnline" />
<button [disabled]="isSaving">Save</button>
`
})
export class AvatarComponent {
avatarUrl = '/assets/avatar.png';
userName = 'Jordan';
isOnline = false;
isSaving = true;
}
bootstrapApplication(AvatarComponent).catch(err => console.error(err));Two-Way Binding with ngModel
Two-way binding keeps a form control and a component property perfectly in sync: typing in the input updates the property, and changing the property elsewhere updates the input. It requires FormsModule to be imported because ngModel is a directive, not built-in template syntax.
Two-way binding on a text input
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { bootstrapApplication } from '@angular/platform-browser';
@Component({
selector: 'app-search-box',
standalone: true,
imports: [FormsModule],
template: `
<input [(ngModel)]="query" placeholder="Search..." />
<p>You typed: {{ query }}</p>
`
})
export class SearchBoxComponent {
query = '';
}
bootstrapApplication(SearchBoxComponent).catch(err => console.error(err));- Interpolation only works inside text content and cannot target attributes directly.
- Property binding is the general-purpose form; interpolation is really shorthand for a property binding to textContent.
- [(ngModel)] is syntactic sugar combining a property binding and an event binding into one — it is often called banana-in-a-box.
- Two-way binding needs FormsModule imported into the component's imports array.
Exercise: Angular Data Binding
Which syntax performs one-way property binding to an element?