Angular Data Binding – Interpolation, Property, Event, Two-Way
🎧 Focus sounds
Soft beat sounds that many learners like while reading. Pick one, press Play, and keep studying.
Keep the volume low. These sounds are for comfort while studying, not a medical treatment. If you have epilepsy or are sensitive to pulsing sounds, use the background noise only.
In this lesson
Data binding connects your component class (data) with the template (what users see). Angular has four kinds, and their brackets tell you which way data flows.
The four bindings, animated#
Pick a binding type and watch where the data moves:
| Syntax | Name | Direction |
|---|---|---|
{{ value }} | interpolation | class → view (text) |
[property]="value" | property binding | class → view (DOM property / input) |
(event)="handler()" | event binding | view → class |
[(ngModel)]="value" | two-way binding | both ways |
Memory trick: [ ] brings data in to the element, ( ) sends events out, and [( )] is “banana in a box”: both.
All four in one component#
// src/app/binding-demo/binding-demo.component.ts
import { Component, signal } from '@angular/core';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-binding-demo',
standalone: true,
imports: [FormsModule], // needed for ngModel
template: `
<h2>{{ title }}</h2> <!-- interpolation -->
<img [src]="logoUrl" [alt]="title + ' logo'" width="48" /> <!-- property binding -->
<button (click)="like()" [disabled]="likes() >= 5">👍 {{ likes() }}</button> <!-- event + property -->
<input [(ngModel)]="name" placeholder="Your name" /> <!-- two-way -->
<p>Hello {{ name || 'stranger' }}</p>
`,
})
export class BindingDemoComponent {
title = 'Java Basics';
logoUrl = '/assets/java.svg';
likes = signal(0);
name = '';
like() { this.likes.update(n => n + 1); }
}
Property binding vs attribute binding#
Property binding sets DOM properties ([value], [disabled], [src], [hidden]). Some HTML attributes have no matching property (ARIA, colspan), so use attr.:
<td [attr.colspan]="span">…</td>
<button [attr.aria-label]="'Remove ' + course.title">×</button>
Class and style bindings#
<li [class.done]="task.done" [class.urgent]="task.priority === 'high'">{{ task.title }}</li>
<div [class]="{ card: true, selected: isSelected, disabled: !enabled }"></div>
<div [style.width.%]="progress">{{ progress }}%</div>
<p [style.color]="balance < 0 ? 'crimson' : 'green'">₹{{ balance }}</p>
Event binding details#
<input (input)="query = $any($event.target).value" /> <!-- $event is the DOM event -->
<input (keyup.enter)="search()" /> <!-- key filters -->
<form (ngSubmit)="save()">…</form> <!-- forms module submit -->
<div (mouseenter)="hover = true" (mouseleave)="hover = false"></div>
Template reference variables#
#name gives a template element a name you can use elsewhere in the template:
<input #search placeholder="Search courses" />
<button (click)="find(search.value); search.value = ''">Search</button>
Two-way binding on your own components: model()#
// src/app/rating/rating.component.ts
import { Component, model } from '@angular/core';
@Component({
selector: 'app-rating',
standalone: true,
template: `
@for (star of [1, 2, 3, 4, 5]; track star) {
<button type="button" (click)="value.set(star)" [attr.aria-label]="star + ' stars'">
{{ star <= value() ? '★' : '☆' }}
</button>
}
`,
})
export class RatingComponent {
value = model(0); // a two-way bindable signal
}
<app-rating [(value)]="myRating" />
<p>You rated {{ myRating }} stars</p>
model() combines an input and an output (valueChange) so parents can use [( )] with your component.
Keep templates simple. If an expression gets longer than a few words ([class.x]="a && (b || c) && !d"), move it into a computed() signal or a method with a clear name. Templates are for displaying, classes are for logic.
Common mistakes#
- Using
[(ngModel)]without importingFormsModule: “Can’t bind to ‘ngModel'”. [src]="'logo.png'"vssrc="logo.png": inside[ ]the value is an expression, so plain strings need quotes.- Calling heavy methods in templates (
{{ calculateTotal() }}): they run on every change detection. Prefercomputedsignals.
Exercise#
- Build a temperature converter: an input bound with
[(ngModel)]and a live Fahrenheit result. - Add a “dark card” toggle button that adds a class with
[class.dark]. - Make a progress bar whose width comes from a number input (
[style.width.%]). - Use the
RatingComponentwith[(value)]and show “Thanks!” after rating.
Hint for 1
celsius = 25; and in the template {{ celsius * 9 / 5 + 32 | number:'1.0-1' }} °F (the number pipe formats decimals, next lesson).
Interview corner#
- Types of data binding? Interpolation, property binding, event binding and two-way binding.
- How does two-way binding work?
[(x)]is shorthand for[x]="val" (xChange)="val = $event". - Property vs attribute binding? Property binding sets DOM properties;
[attr.name]sets HTML attributes. - What is a template reference variable? A
#refname for an element or component usable elsewhere in the template.
Summary#
{{ }}and[ ]move data into the view,( )brings events back,[( )]does both.- Class, style and attribute bindings handle styling and accessibility.
model()gives your components two-way binding.
Next: control flow (@if, @for) and pipes.
Quick quiz
3 questions. Check what stuck and earn 2 XP for each right answer.
Progress is saved in this browser. Create a free account to keep it on every device.
Get new lessons in your inbox
One email when we publish a new tutorial or guide. No spam, unsubscribe in one click.