Data Binding
Data binding connects your component class to its template. Angular has four kinds, and their brackets tell you exactly which way the data flows.
On this page · 5 min · Beginner
On this page
- Learning objectives
- Explanation
- Syntax
- Code example
- Step by step
- Real-world use
- Common mistakes
- Best practices
- Remember this
- Practice exercise
- Mini quiz
- Related topics
- My notes
- Reading time
- 5 min
- Difficulty
- Beginner
- Updated
- Oct 28, 2026
Related tutorials
Learning objectives#
- Name the four binding types and their syntax
- Tell which direction each one flows
- Combine them in one form
- Choose the right binding for a task
Explanation#
Interpolation {{ value }} — class → view, as text.
Property binding [property]="value" — class → view, into a DOM or component property: [disabled]="isSaving", [src]="imageUrl", [price]="p.price".
Event binding (event)="handler($event)" — view → class: (click), (input), (submit), or a child component’s output.
Two-way binding [(model)]="value" — both ways at once. It is shorthand for a property binding plus an event binding. Used with ngModel in forms and with model() inputs on components.
Remember the “banana in a box” [( )]: square brackets bring data in, round brackets send events out.
Syntax#
<p>{{ name }}</p> <!-- class → view (text) -->
<button [disabled]="saving">Save</button> <!-- class → view (property) -->
<button (click)="save()">Save</button> <!-- view → class (event) -->
<input [(ngModel)]="name" /> <!-- both ways -->
Code example: All four bindings in one profile editor#
import { Component, signal } from '@angular/core';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-profile',
imports: [FormsModule],
template: `
<h2>Hello, {{ name() || 'stranger' }}!</h2> <!-- interpolation -->
<img [src]="avatarUrl" [alt]="'Avatar of ' + name()" width="64" /> <!-- property -->
<input [(ngModel)]="nameModel" (ngModelChange)="name.set($event)" placeholder="Your name" /> <!-- two-way + event -->
<button [disabled]="!name()" (click)="save()">Save</button> <!-- property + event -->
@if (saved()) { <p>Saved {{ name() }} ✔</p> }
`,
})
export class Profile {
name = signal('');
nameModel = '';
saved = signal(false);
avatarUrl = 'https://i.pravatar.cc/64';
save() {
this.saved.set(true);
}
}
The heading starts as “Hello, stranger!” and the Save button is disabled. Typing “Asha” updates the heading live and enables the button. Clicking Save shows “Saved Asha ✔”.
This example is illustrative. Copy or download it and run it in your own environment; the expected output is shown above.
Step-by-step explanation#
- {{ name() || "stranger" }} displays text from the class.
- [src] and [alt] set element properties from class values.
- [(ngModel)] keeps nameModel and the input in sync; (ngModelChange) also copies each change into the name signal.
- [disabled]="!name()" enables Save only when a name exists.
- (click)="save()" calls a class method.
Real-world use case#
A checkout form uses interpolation for totals, property binding to disable “Pay” while saving, event binding for buttons, and two-way binding for the coupon field.
Common mistakes#
[src]="{{ url }}" is wrong. Inside property bindings write plain expressions: [src]="url".
[(ngModel)] needs FormsModule in the component’s imports, or you get “Can’t bind to ngModel”.
aria-* and colspan are attributes. Use [attr.aria-label]="label" for them.
Best practices#
- Use the simplest binding that works
- Prefer signals for component state
- Use [attr.x] for pure HTML attributes
- Keep event handlers as method calls
Remember this#
{{ }} and [ ] = data in. ( ) = events out. [( )] = both.
Banana in a box: [( )].
ngModel needs FormsModule.
Practice exercise#
Your task: Make a quantity picker: a number displayed with {{ }}, a "−" button disabled at 1, and a "+" button, all bound to a qty signal.
Need a hint?
Show solution
import { Component, signal } from '@angular/core';
@Component({
selector: 'app-qty',
template: `
<button [disabled]="qty() <= 1" (click)="decrease()">−</button>
<span> {{ qty() }} </span>
<button (click)="increase()">+</button>
`,
})
export class Qty {
qty = signal(1);
increase() { this.qty.update(q => q + 1); }
decrease() { this.qty.update(q => Math.max(1, q - 1)); }
}
Mini quiz#
Which syntax is event binding?
Want more? Practise all Angular MCQs · Angular interview questions
My notes#
Saved in this browser.