Angular Templates & Data Binding
In Angular, a template is the HTML file that defines what a component displays on the screen. However, Angular templates are not plain HTML — they include special Angular syntax that connects the HTML to the component's TypeScript class. This connection between the template and the class is called data binding.
Data binding is the mechanism that keeps the screen and the application's data in sync. When data in the TypeScript class changes, the screen updates automatically. When the user interacts with the screen, the TypeScript class responds. Angular provides four types of data binding to handle different scenarios.
The Four Types of Data Binding
1. Interpolation — Displaying Data
Interpolation is the simplest form of data binding. It takes a value from the TypeScript class and displays it inside the HTML template using double curly braces {{ }}.
Data flows in one direction: from the TypeScript class to the template.
// greeting.component.ts
export class GreetingComponent {
firstName = 'Maria';
itemCount = 5;
totalPrice = 149.99;
}
<!-- greeting.component.html -->
<h2>Hello, {{ firstName }}!</h2>
<p>You have {{ itemCount }} items in your cart.</p>
<p>Total: ${{ totalPrice }}</p>
Output on screen:
Hello, Maria!
You have 5 items in your cart.
Total: $149.99
Interpolation also supports simple JavaScript expressions:
<p>{{ 10 + 5 }}</p> <!-- Displays: 15 -->
<p>{{ firstName.toUpperCase() }}</p> <!-- Displays: MARIA -->
<p>{{ itemCount > 0 ? 'In stock' : 'Out of stock' }}</p> <!-- Displays: In stock -->
2. Property Binding — Binding to HTML Attributes
Property binding sets an HTML element's property (like src, disabled, or href) to a value from the TypeScript class. The property name is wrapped in square brackets [ ].
Data flows in one direction: from the TypeScript class to the HTML element's property.
// image-display.component.ts
export class ImageDisplayComponent {
logoUrl = 'assets/images/logo.png';
logoAlt = 'Company Logo';
isButtonDisabled = true;
linkUrl = 'https://www.example.com';
}
<!-- image-display.component.html -->
<img [src]="logoUrl" [alt]="logoAlt">
<button [disabled]="isButtonDisabled">Submit</button>
<a [href]="linkUrl">Visit Website</a>
Property binding differs from interpolation in an important way. Interpolation converts values to strings and inserts them into the content area. Property binding sets actual DOM properties, which can accept any data type — strings, numbers, booleans, and objects.
Difference Between Attribute and Property Binding
HTML attributes and DOM properties are not always the same thing. For example, disabled as an HTML attribute just needs to exist (with any value) to disable a button. But as a DOM property, Angular needs a boolean true or false. Property binding always works with the DOM property, not the HTML attribute.
3. Event Binding — Responding to User Actions
Event binding listens for user events (like clicks, key presses, or mouse movements) and calls a method in the TypeScript class when the event occurs. The event name is wrapped in parentheses ( ).
Data flows from the template to the TypeScript class.
// button-demo.component.ts
export class ButtonDemoComponent {
message = 'No button clicked yet.';
inputValue = '';
onSaveClick() {
this.message = 'Save button was clicked!';
}
onInputChange(event: Event) {
const input = event.target as HTMLInputElement;
this.inputValue = input.value;
}
}
<!-- button-demo.component.html -->
<button (click)="onSaveClick()">Save</button>
<p>{{ message }}</p>
<input (input)="onInputChange($event)" placeholder="Type something">
<p>Typed: {{ inputValue }}</p>
The $event is a special variable that Angular passes automatically when an event occurs. It contains information about the event, such as the target element and the value typed into an input field.
Common Events
(click)="method()" <!-- Mouse click -->
(dblclick)="method()" <!-- Double click -->
(keyup)="method()" <!-- Key released -->
(keydown)="method()" <!-- Key pressed -->
(mouseover)="method()" <!-- Mouse hovers over element -->
(input)="method($event)" <!-- Input value changes -->
(change)="method()" <!-- Select or checkbox changes -->
(submit)="method()" <!-- Form submitted -->
(focus)="method()" <!-- Element receives focus -->
(blur)="method()" <!-- Element loses focus -->
4. Two-Way Binding — Syncing Input Fields
Two-way binding keeps a form input and a TypeScript class property in perfect sync. When the user types in the input field, the property updates. When the property changes in code, the input field updates. This uses the [(ngModel)] directive.
The syntax [( )] is sometimes called the "banana in a box" — the box [ ] represents property binding, and the banana ( ) represents event binding. Together they create two-way communication.
// login.component.ts
export class LoginComponent {
username = '';
password = '';
onLogin() {
console.log('Username:', this.username);
console.log('Password:', this.password);
}
}
<!-- login.component.html -->
<h3>Login Form</h3>
<input [(ngModel)]="username" placeholder="Enter username">
<p>Hello, {{ username }}!</p>
<input [(ngModel)]="password" type="password" placeholder="Enter password">
<button (click)="onLogin()">Login</button>
As the user types in the username input, the paragraph below immediately displays the typed text. The username property in the class always reflects what is in the input field.
Enabling ngModel
To use [(ngModel)], the FormsModule must be imported in the application's module file:
// app.module.ts
import { FormsModule } from '@angular/forms';
@NgModule({
imports: [
BrowserModule,
FormsModule // ← Add this
]
})
export class AppModule { }
Template Reference Variables
A template reference variable gives a name to an HTML element inside the template. This allows direct access to the element's value or properties without going through the TypeScript class.
<input #nameInput placeholder="Enter your name">
<button (click)="greet(nameInput.value)">Greet</button>
<p>{{ greeting }}</p>
export class ExampleComponent {
greeting = '';
greet(name: string) {
this.greeting = 'Hello, ' + name + '!';
}
}
The #nameInput creates a reference variable pointing to the input element. When the button is clicked, nameInput.value passes the current value of the input to the greet() method directly — no two-way binding needed.
Data Binding Summary Table
Type | Syntax | Direction | Example
------------------|---------------------|------------------------|----------------------------
Interpolation | {{ value }} | Class → Template | <p>{{ title }}</p>
Property Binding | [property]="value" | Class → HTML Property | <img [src]="imageUrl">
Event Binding | (event)="method()" | Template → Class | <button (click)="save()">
Two-Way Binding | [(ngModel)]="prop" | Class ↔ Template | <input [(ngModel)]="name">
Practical Example — Live Search Input
This example demonstrates multiple binding types working together:
// search.component.ts
export class SearchComponent {
searchQuery = '';
results: string[] = ['Angular', 'React', 'Vue', 'Svelte', 'Ember'];
get filteredResults(): string[] {
if (!this.searchQuery) return this.results;
return this.results.filter(r =>
r.toLowerCase().includes(this.searchQuery.toLowerCase())
);
}
clearSearch() {
this.searchQuery = '';
}
}
<!-- search.component.html -->
<h3>Framework Search</h3>
<input [(ngModel)]="searchQuery" placeholder="Search frameworks...">
<button (click)="clearSearch()" [disabled]="!searchQuery">Clear</button>
<p>Found {{ filteredResults.length }} result(s):</p>
<ul>
<li *ngFor="let item of filteredResults">{{ item }}</li>
</ul>
In this example:
[(ngModel)]keepssearchQueryin sync with the input field (two-way binding).(click)="clearSearch()"clears the search when the button is clicked (event binding).[disabled]="!searchQuery"disables the button when the search field is empty (property binding).{{ filteredResults.length }}displays the count of results (interpolation).
Summary
Data binding is the mechanism that connects the TypeScript class to the HTML template. Angular provides four types: interpolation ({{ }}) displays class data in the template; property binding ([ ]) sets HTML element properties; event binding (( )) responds to user actions by calling class methods; two-way binding ([( )]) with ngModel keeps form inputs and class properties in sync. Template reference variables (#name) provide direct access to HTML elements inside the template. Together, these four binding types make Angular templates dynamic and interactive.
