Angular Data Binding
Read one Angular interview question at a time, then flip for the complete explanation, example, and code.
Read one Angular interview question at a time, then flip for the complete explanation, example, and code.
Angular Interview Questions · Angular Data Binding Companion Article
Angular data binding is the mechanism that connects a component's TypeScript data with the HTML template displayed in the browser. Instead of manually finding DOM elements and changing their values, Angular keeps the component and the template synchronized through its binding syntax. Data binding is used throughout Angular applications for displaying values, updating element properties, responding to user actions, handling form fields, passing information between components, and rendering collections of data. This chapter explains the main data-binding techniques and shows where each technique is useful in real Angular applications.
An Angular component normally contains two important parts:
Data binding creates a connection between these two parts.
For example, suppose a component contains:
export class ProfileComponent {
username = 'Rahul';
}
The template can display the value using interpolation:
<h2>Welcome, {{ username }}</h2>
Angular reads the username property from the component and displays:
Welcome, Rahul
If the component value changes and Angular performs its normal rendering/update process, the displayed value is updated accordingly.
Angular applications commonly use four basic binding styles:
| Binding Type | Syntax | Direction | Main Purpose |
|---|---|---|---|
| Interpolation | {{ value }} | Component → Template | Display text |
| Property Binding | [property]="value" | Component → Template | Set DOM/component properties |
| Event Binding | (event)="method()" | Template → Component | Handle events |
| Two-Way Binding | [(...)]="value" | Both directions | Synchronize values |
A useful way to remember them is:
Component → Template
Interpolation / Property Binding
Template → Component
Event Binding
Component ↔ Template
Two-Way Binding
One-way data binding means information moves in one direction.
The direction can be:
Component → Template
or:
Template Event → Component
Interpolation and property binding usually send component data to the template, while event binding sends information about user actions back to the component.
Example:
export class ProductComponent {
productName = 'Laptop';
}
<h2>{{ productName }}</h2>
Here the component provides the value and the template displays it.
The template is not directly changing the productName property.
One-way binding provides a predictable data flow.
It is useful when:
It also makes it easier to understand where a value originated.
Interpolation is one of the simplest Angular binding techniques.
Syntax:
{{ expression }}
It is mainly used to display component values as text.
Component:
export class UserComponent {
firstName = 'Amit';
age = 28;
}
Template:
<p>Name: {{ firstName }}</p>
<p>Age: {{ age }}</p>
Output:
Name: Amit
Age: 28
Interpolation can evaluate simple template expressions.
<p>{{ firstName.toUpperCase() }}</p>
<p>{{ age + 1 }}</p>
<p>{{ firstName + ' is a user' }}</p>
Angular evaluates the expression and displays its result.
Complex business logic should normally remain in the component rather than being placed directly inside the template.
Instead of:
<p>{{ price * quantity - price * quantity * discount / 100 }}</p>
a component property or method can make the intent easier to understand.
Property binding allows a component value to be assigned to a property of:
Syntax:
[property]="expression"
Example:
export class ImageComponent {
imageUrl = '/images/angular-logo.png';
}
<img [src]="imageUrl">
Angular evaluates imageUrl and assigns its value to the element's src property.
Property binding is particularly useful for Boolean states.
export class FormComponent {
isSaving = true;
}
<button [disabled]="isSaving">
Save
</button>
When isSaving is true, the button is disabled.
When it becomes false, the button becomes available.
Property binding is also the basis of parent-to-child communication.
<app-user [username]="currentUser"></app-user>
In this example, the parent passes the value of currentUser to a property exposed by the child component.
Interpolation and property binding often appear similar, but they serve slightly different purposes.
Example using interpolation:
<img src="{{ imageUrl }}">
Equivalent property binding:
<img [src]="imageUrl">
For simple text content, interpolation is usually easier to read.
<h2>{{ title }}</h2>
For element properties, property binding is usually clearer.
<button [disabled]="isDisabled">
Property binding also preserves the underlying value type instead of treating everything as text.
For example:
<app-chart [data]="chartData"></app-chart>
chartData can remain an object or array.
Event binding lets Angular respond to events generated by:
Syntax:
(event)="statement"
Example:
<button (click)="showMessage()">
Click Me
</button>
Component:
export class DemoComponent {
showMessage() {
console.log('Button clicked');
}
}
When the button is clicked, Angular calls showMessage().
Frequently used events include:
(click)="..."
(change)="..."
(input)="..."
(submit)="..."
(focus)="..."
(blur)="..."
(keydown)="..."
(keyup)="..."
(mouseenter)="..."
(mouseleave)="..."
Example:
<input (keyup)="search()">
Angular provides the special $event variable for event binding.
It contains information associated with the event.
Example:
<input (input)="readValue($event)">
Component:
readValue(event: Event) {
const input = event.target as HTMLInputElement;
console.log(input.value);
}
For a button click, $event contains the click event.
For a keyboard event, it contains keyboard-related information.
For custom component events, it contains the value emitted by the child component.
Two-way binding allows information to travel in both directions:
Component → Template
Template → Component
This is useful when the user must edit a value that is also stored in the component.
Angular represents two-way binding using:
[(...)]
Because the syntax combines square brackets and parentheses, developers sometimes call it banana-in-a-box syntax.
[()]
A common example is binding an input field to a component property.
Component:
export class UserComponent {
username = '';
}
Template:
<input [(ngModel)]="username">
<p>You entered: {{ username }}</p>
When the user types into the input:
usernameusernameNo additional input event handler is required for this basic synchronization.
ngModel belongs to Angular's forms functionality.
For a standalone component, import FormsModule when using ngModel.
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-profile',
imports: [FormsModule],
templateUrl: './profile.component.html'
})
export class ProfileComponent {
username = '';
}
Then:
<input [(ngModel)]="username">
Without the appropriate forms import, Angular cannot use the ngModel directive.
Two-way binding can be understood as a combination of:
Property binding + Event binding
Conceptually:
<input
[ngModel]="username"
(ngModelChange)="username = $event">
is represented more conveniently as:
<input [(ngModel)]="username">
This is why Angular uses both brackets and parentheses.
Consider an input field.
One-way property binding:
<input [value]="username">
The component provides the value to the input.
If the user types something else, the username component property is not automatically updated.
Two-way binding:
<input [(ngModel)]="username">
Now changes can flow in both directions.
Use two-way binding when synchronization is genuinely required rather than making every value two-way by default.
Angular bindings are not limited to strings and numbers.
Complete JavaScript or TypeScript objects can be passed through property binding.
Example:
export class UserComponent {
user = {
id: 101,
name: 'Neha',
role: 'Developer'
};
}
Individual values can be displayed using interpolation:
<p>{{ user.name }}</p>
<p>{{ user.role }}</p>
The entire object can also be passed to another component:
<app-user-card [user]="user"></app-user-card>
This is usually better than converting an object into a string when the receiving component needs the actual structured data.
Objects frequently contain nested properties.
employee = {
name: 'Ravi',
address: {
city: 'Pune',
state: 'Maharashtra'
}
};
Template:
<p>{{ employee.name }}</p>
<p>{{ employee.address.city }}</p>
Output:
Ravi
Pune
Data loaded from an API may not be immediately available.
Angular templates can safely access values with optional chaining when appropriate.
<p>{{ employee?.name }}</p>
For nested data:
<p>{{ employee?.address?.city }}</p>
This is useful when a value may temporarily be null or undefined.
Arrays are commonly used for:
Example:
technologies = ['Angular', 'TypeScript', 'RxJS'];
An individual item can be displayed:
<p>{{ technologies[0] }}</p>
Output:
Angular
Normally, however, arrays are rendered using Angular's template control-flow features rather than accessing each item manually.
For example:
@for (technology of technologies; track technology) {
<p>{{ technology }}</p>
}
This produces one element for each array item.
Real applications frequently work with arrays containing objects.
products = [
{ id: 1, name: 'Laptop', price: 60000 },
{ id: 2, name: 'Keyboard', price: 2000 },
{ id: 3, name: 'Mouse', price: 900 }
];
Template:
@for (product of products; track product.id) {
<div>
<h3>{{ product.name }}</h3>
<p>Price: {{ product.price }}</p>
</div>
}
The component stores the data while the template determines how that data is presented.
Component state can control CSS classes.
Example:
isActive = true;
Template:
<div [class.active]="isActive">
User Account
</div>
When isActive is true, the active class is applied.
This technique is useful for:
Styles can also be controlled using component values.
textSize = 20;
<p [style.font-size.px]="textSize">
Angular Data Binding
</p>
Angular converts the value into the appropriate style value.
Dynamic style binding should be used when a visual value genuinely depends on application state. Normal static styling is better kept in CSS.
Large Angular applications are divided into many components.
A parent component often needs to provide data to one of its children.
Conceptually:
Parent Component
↓
Child Component
Angular provides input bindings for this purpose.
A child can expose an input.
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-user-card',
template: `<h3>{{ username }}</h3>`
})
export class UserCardComponent {
@Input() username = '';
}
The parent can pass data using property binding:
<app-user-card [username]="currentUsername"></app-user-card>
Parent component:
currentUsername = 'Anjali';
The child receives:
Anjali
Instead of sending many individual properties, a parent can pass an object.
Parent:
user = {
id: 10,
name: 'Akash',
department: 'Engineering'
};
Parent template:
<app-user-card [user]="user"></app-user-card>
Child:
@Input() user!: {
id: number;
name: string;
department: string;
};
Child template:
<h3>{{ user.name }}</h3>
<p>{{ user.department }}</p>
Passing an object can be convenient when multiple related values belong together.
Sometimes the opposite communication is required.
For example, a child component may need to tell its parent that:
The flow becomes:
Child Component
↓
Parent Component
A traditional Angular approach uses @Output() together with EventEmitter.
Child:
import { Component, EventEmitter, Output } from '@angular/core';
@Component({
selector: 'app-child',
template: `
<button (click)="notifyParent()">
Notify Parent
</button>
`
})
export class ChildComponent {
@Output() selected = new EventEmitter<string>();
notifyParent() {
this.selected.emit('Angular');
}
}
Parent template:
<app-child
(selected)="handleSelection($event)">
</app-child>
Parent component:
handleSelection(value: string) {
console.log(value);
}
The value emitted by the child becomes available as $event in the parent template.
A child event can emit complete structured data.
@Output() productSelected =
new EventEmitter<{ id: number; name: string }>();
selectProduct() {
this.productSelected.emit({
id: 101,
name: 'Laptop'
});
}
Parent:
<app-product
(productSelected)="onProductSelected($event)">
</app-product>
Component:
onProductSelected(product: { id: number; name: string }) {
console.log(product.name);
}
This pattern is commonly used in reusable components.
A simple component communication flow looks like this:
Parent Component
|
| Property/Input Binding
v
Child Component
|
| Output/Event Binding
v
Parent Component
Parent-to-child communication usually represents data flowing downward.
Child-to-parent communication usually represents an event or action flowing upward.
Keeping this flow clear makes component behavior easier to maintain.
Suppose a parent contains product data.
products = [
{ id: 1, name: 'Laptop' },
{ id: 2, name: 'Mouse' }
];
selectedProduct = '';
onSelected(name: string) {
this.selectedProduct = name;
}
Parent template:
<app-product-list
[products]="products"
(selected)="onSelected($event)">
</app-product-list>
<p>Selected Product: {{ selectedProduct }}</p>
The parent sends products to the child.
The child displays the products and emits the selected product back to the parent.
This combines:
These patterns appear frequently in real Angular applications.
Data binding is involved in almost every Angular screen.
<input [(ngModel)]="email">
<input [(ngModel)]="password">
<button (click)="login()">Login</button>
<button [disabled]="isSubmitting">
Submit
</button>
<h2>{{ user.name }}</h2>
<p>{{ user.email }}</p>
<img [src]="user.profileImage">
<input
[(ngModel)]="searchText"
(keyup.enter)="search()">
<app-product
[product]="selectedProduct"
(addToCart)="addProduct($event)">
</app-product>
Different binding techniques are often combined within the same feature.
Incorrect:
<img src="imageUrl">
This gives the browser the literal text imageUrl.
Correct:
<img [src]="imageUrl">
Incorrect:
<button click="save()">Save</button>
Correct:
<button (click)="save()">Save</button>
Using:
<input [(ngModel)]="name">
requires the appropriate Angular forms functionality to be available, commonly through FormsModule.
Avoid placing computationally expensive work directly inside frequently evaluated template expressions.
Instead of repeatedly performing complicated calculations inside the HTML, calculate or derive the value in an appropriate component/service design.
This keeps templates easier to understand and can avoid unnecessary work.
A child should not casually modify an object received from its parent.
Shared object references can make application state difficult to understand.
Prefer clearly defined ownership of state and explicit events when a child needs to request a change.
Two-way binding is convenient, but it should not replace clear application state design.
Use:
[(ngModel)]
when true synchronization is helpful, particularly for suitable form controls.
Use one-way data flow when the component should remain the clear owner of a value.
A simple decision guide is:
Need to display text?
→ Interpolation
Need to set an element/component property?
→ Property Binding
Need to respond to user action?
→ Event Binding
Need UI and component value synchronized?
→ Two-Way Binding
Need to send data from parent to child?
→ Input / Property Binding
Need to notify parent from child?
→ Output / Event Binding
<!-- Interpolation -->
<p>{{ username }}</p>
<!-- Property Binding -->
<img [src]="imageUrl">
<!-- Boolean Property Binding -->
<button [disabled]="isDisabled">Save</button>
<!-- Event Binding -->
<button (click)="save()">Save</button>
<!-- Event Data -->
<input (input)="handleInput($event)">
<!-- Two-Way Binding -->
<input [(ngModel)]="username">
<!-- Class Binding -->
<div [class.active]="isActive"></div>
<!-- Style Binding -->
<p [style.font-size.px]="fontSize"></p>
<!-- Parent to Child -->
<app-child [user]="user"></app-child>
<!-- Child to Parent -->
<app-child (selected)="onSelected($event)"></app-child>
{{ }} and is mainly used for displaying values.[property].(event).[()].[(ngModel)] is commonly used for two-way form control binding.$event represents the data associated with an event.Angular data binding is therefore more than a syntax feature. It is one of the core mechanisms through which Angular components display application state, accept user input, react to interactions, and communicate with one another.