Angular Templates
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 Templates Companion Article
Angular templates define what users see in the browser and how that user interface communicates with component data. A template looks similar to HTML, but Angular extends normal HTML with features such as interpolation, property binding, event binding, template variables, expressions, and two-way binding. Instead of building a completely static page, Angular templates allow the displayed content to react to application data and user actions.
For example, a component may contain:
export class UserComponent {
userName = 'Rahul';
isActive = true;
}
The template can display and use this data:
<h2>{{ userName }}</h2>
<p [class.active]="isActive">User Status</p>
Here, the HTML is connected directly to the component class.
Angular template syntax is the set of rules Angular provides for connecting HTML with component data and application logic.
A normal HTML page displays fixed content:
<h1>Welcome</h1>
An Angular template can display dynamic content:
<h1>Welcome {{ userName }}</h1>
Angular template syntax commonly includes:
{{ }} for text interpolation[property] for property binding[attr.attribute] for attribute binding[class.className] for class binding[style.property] for style binding(event) for event binding[(ngModel)] for common form-based two-way binding#variableName for template reference variablesA template should mainly describe the user interface. Complex business logic should normally remain inside the component or another TypeScript class rather than being placed directly in HTML.
export class ProductComponent {
productName = 'Laptop';
price = 55000;
available = true;
buyProduct() {
console.log('Product purchased');
}
}
<h2>{{ productName }}</h2>
<p>Price: ₹{{ price }}</p>
<button [disabled]="!available" (click)="buyProduct()">
Buy Now
</button>
This example combines interpolation, property binding, template expressions, and event binding.
Text interpolation displays component values inside the template.
{{ expression }}
export class ProfileComponent {
name = 'Amit';
role = 'Angular Developer';
}
<h2>{{ name }}</h2>
<p>{{ role }}</p>
Angular evaluates the expressions and displays their values.
The rendered result would be similar to:
Amit
Angular Developer
Interpolation is not limited to simple variables.
<p>{{ firstName + ' ' + lastName }}</p>
<p>{{ price * quantity }}</p>
<p>{{ isLoggedIn ? 'Welcome' : 'Please Login' }}</p>
Method calls can also be used:
<p>{{ getFullName() }}</p>
However, methods called from templates may be evaluated frequently during rendering and change detection. Expensive calculations are better handled outside the template.
Interpolation is suitable for:
Property binding passes data from the component to a property of an HTML element, directive, or Angular component.
[property]="expression"
export class ImageComponent {
imageUrl = 'assets/angular-logo.png';
}
<img [src]="imageUrl">
The value of imageUrl is assigned to the DOM element's src property.
Another example:
export class FormComponent {
formDisabled = true;
}
<button [disabled]="formDisabled">Submit</button>
If formDisabled is true, the button becomes disabled.
Static HTML:
<img src="assets/logo.png">
Dynamic Angular property binding:
<img [src]="logoUrl">
Use property binding when the value must come from component data or an Angular expression.
<input [value]="userName">
<img [src]="profileImage">
<button [disabled]="isDisabled">
Save
</button>
<a [href]="websiteUrl">
Visit Website
</a>
Property binding represents one-way communication:
Component Data
↓
Template
Property binding and attribute binding are related but are not identical.
Property binding normally updates a DOM property. Attribute binding explicitly updates an HTML attribute.
[attr.attributeName]="expression"
export class TableComponent {
columnCount = 3;
}
<td [attr.colspan]="columnCount">
Product Information
</td>
Attribute binding is especially useful for attributes that do not have a convenient corresponding DOM property.
export class ButtonComponent {
buttonDescription = 'Close dialog';
}
<button [attr.aria-label]="buttonDescription">
X
</button>
ARIA attributes are common examples of situations where attribute binding is useful.
When an attribute-binding expression evaluates to null, Angular can remove that attribute.
<button [attr.title]="showHelp ? 'Click to continue' : null">
Continue
</button>
Class binding dynamically adds or removes CSS classes based on component data.
<div [class.active]="isActive">
Account
</div>
If isActive is true, Angular applies the active class.
export class AccountComponent {
isActive = true;
}
.active {
font-weight: bold;
}
Angular can also bind the complete class value.
export class AlertComponent {
currentClass = 'success-message';
}
<div [class]="currentClass">
Operation completed
</div>
<span [class.available]="stock > 0">
{{ stock > 0 ? 'In Stock' : 'Out of Stock' }}
</span>
Class binding is useful for:
Style binding changes an element's inline CSS style dynamically.
[style.property]="expression"
export class ProgressComponent {
textColor = 'green';
}
<p [style.color]="textColor">
Completed
</p>
Angular allows units to be included in style bindings.
export class BoxComponent {
boxWidth = 250;
}
<div [style.width.px]="boxWidth">
Content
</div>
Other units can also be used where appropriate:
<div [style.width.%]="progress"></div>
<p [style.color]="isError ? 'red' : 'green'">
{{ message }}
</p>
Style binding is useful when a style value genuinely depends on application state. For larger styling changes involving reusable visual states, class binding is often easier to maintain.
Event binding sends information from the template to the component when a user or browser event occurs.
(event)="statement"
export class CounterComponent {
count = 0;
increment() {
this.count++;
}
}
<button (click)="increment()">Increase</button>
<p>Count: {{ count }}</p>
When the user clicks the button, Angular calls increment().
The data flow is:
User Action
↓
Template Event
↓
Component Method
<button (click)="save()">Save</button>
<input (input)="onInput($event)">
<input (keyup)="onKeyUp($event)">
<input (focus)="onFocus()">
<input (blur)="onBlur()">
<form (submit)="submitForm()">
Angular provides the special $event variable for accessing information about the current event.
<input (input)="onInput($event)">
Component:
onInput(event: Event) {
const input = event.target as HTMLInputElement;
console.log(input.value);
}
$event contains the event object generated by the browser or component.
Templates can react to particular keyboard events.
<input (keyup.enter)="search()">
The search() method runs when Enter is pressed.
Two-way binding allows data to move in both directions between the component and the template.
Conceptually:
Component
↓
Template
Component
↑
Template
A common example is a form input whose value should stay synchronized with a component property.
export class UserComponent {
userName = '';
}
<input [(ngModel)]="userName">
<p>Hello {{ userName }}</p>
When the user enters text, userName changes. When userName changes programmatically, the input can also reflect the new value.
The syntax:
[(ngModel)]="userName"
combines property-style and event-style communication.
The [()] syntax is sometimes informally called banana-in-a-box syntax because of the shape of the brackets and parentheses.
When using ngModel, the appropriate Angular forms support must be imported into the application or component.
For standalone components, this commonly means importing FormsModule.
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-user',
standalone: true,
imports: [FormsModule],
templateUrl: './user.component.html'
})
export class UserComponent {
userName = '';
}
It is commonly used for:
For complex enterprise forms, Angular's reactive forms approach may provide clearer control over validation and form state.
A template expression is code Angular evaluates to produce a value.
Examples:
{{ userName }}
{{ price * quantity }}
{{ firstName + ' ' + lastName }}
{{ isLoggedIn ? 'Logout' : 'Login' }}
<img [src]="imageUrl">
The following are examples of expressions:
userName
price * quantity
firstName + ' ' + lastName
isLoggedIn ? 'Logout' : 'Login'
imageUrl
This is easy to understand:
<p>{{ totalPrice }}</p>
A long calculation directly inside a template is harder to maintain:
<p>{{ price * quantity - price * quantity * discount / 100 + deliveryCharge }}</p>
It may be clearer to calculate the result in TypeScript and expose a meaningful property or method.
Template expressions should generally be:
Template statements respond to events.
Example:
<button (click)="saveUser()">Save</button>
Here:
saveUser()
is executed because of the click event.
A statement may also update a property:
<button (click)="count = count + 1">
Increase
</button>
Another example:
<button (click)="selectedProduct = product">
Select
</button>
Consider:
<p>{{ userName }}</p>
userName is evaluated to produce a value. It is a template expression.
Now consider:
<button (click)="saveUser()">Save</button>
saveUser() is executed in response to an event. In this context, it is a template statement.
A useful distinction is:
| Template Expression | Template Statement |
|---|---|
| Produces a value | Performs an action |
| Common in interpolation | Common in event binding |
| Common in property binding | Runs after an event |
Example: price * quantity | Example: save() |
Angular templates can introduce variables that are available within a particular template context.
A common example appears when iterating over data.
With modern Angular control flow:
@for (product of products; track product.id; let i = $index) {
<p>{{ i + 1 }}. {{ product.name }}</p>
}
Here:
product
i
are variables available within the relevant template block.
The variable product represents the current item, while i receives the current index.
Template variables are useful when working with:
Their scope normally belongs to the template region in which Angular creates them.
A template reference variable provides a reference to an element, component, directive, or other template object.
#variableName
<input #nameInput>
<button (click)="showName(nameInput.value)">
Show Name
</button>
Here:
#nameInput
creates a reference to the input element.
The button can then access:
nameInput.value
showName(name: string) {
console.log(name);
}
<input #searchBox type="text">
<button (click)="search(searchBox.value)">
Search
</button>
Template reference variables are useful when a template needs direct access to a local element or Angular object without creating a component property for every small interaction.
A template reference variable should only be used where it is available in the template's scope. It should not be treated as a global application variable.
Most Angular template features become easier to understand when they are grouped by the direction in which information moves.
These features mainly move or expose data from TypeScript to the UI:
Interpolation
Property Binding
Attribute Binding
Class Binding
Style Binding
Example:
<h2>{{ productName }}</h2>
<img [src]="productImage">
<button [disabled]="soldOut">Buy</button>
Event binding moves information generated by user interaction toward the component.
<button (click)="addToCart()">Add to Cart</button>
Flow:
User clicks button
↓
Angular detects click
↓
addToCart() executes
↓
Component state can change
Two-way binding synchronizes values in both directions.
<input [(ngModel)]="searchText">
Flow:
Component → Input
Component ← Input
Interpolation and property binding can sometimes appear to accomplish similar tasks.
For example:
<img src="{{ imageUrl }}">
and:
<img [src]="imageUrl">
Both can provide a dynamic image URL.
Property binding is generally clearer when working specifically with element properties:
<img [src]="imageUrl">
Interpolation is naturally suited to text:
<p>Welcome {{ userName }}</p>
A useful rule is:
Dynamic text → interpolation
Dynamic element property → property binding
These two concepts are easy to confuse.
Consider:
<input value="Angular">
HTML initially creates an attribute named value. The browser also exposes a corresponding DOM property.
Angular property binding:
<input [value]="courseName">
updates the element property.
Attribute binding:
<td [attr.colspan]="columnCount">
explicitly works with the HTML attribute.
Use normal property binding when the target is available as a DOM or Angular property. Use attr. when an actual attribute needs to be controlled.
Both can dynamically change an element's appearance.
Class binding:
<p [class.error]="hasError">
Invalid value
</p>
Style binding:
<p [style.color]="hasError ? 'red' : 'green'">
Status
</p>
Class binding is usually better when several CSS rules represent one visual state.
For example:
.error {
color: red;
font-weight: bold;
border-left: 3px solid;
}
<p [class.error]="hasError">
Invalid value
</p>
Style binding is convenient when only a particular style value needs to change dynamically.
Property binding and event binding work in opposite directions.
<button [disabled]="isDisabled">Save</button>
Component → Template
<button (click)="save()">Save</button>
Template → Component
Remember:
[property] = component sends data
(event) = template sends an event
The following small example combines several Angular template concepts.
export class ProductComponent {
productName = 'Wireless Keyboard';
productImage = 'assets/keyboard.jpg';
price = 1499;
stock = 5;
quantity = 1;
selected = false;
addToCart() {
console.log('Product added to cart');
}
}
<div [class.selected]="selected">
<img
[src]="productImage"
[attr.alt]="productName">
<h2>{{ productName }}</h2>
<p>Price: ₹{{ price }}</p>
<p
[style.fontWeight]="stock > 0 ? 'bold' : 'normal'">
{{ stock > 0 ? 'In Stock' : 'Out of Stock' }}
</p>
<input
type="number"
[(ngModel)]="quantity">
<button
[disabled]="stock === 0"
(click)="addToCart()">
Add to Cart
</button>
</div>
This single template demonstrates:
This is closer to how template features are used in real Angular applications: several binding mechanisms work together to represent and update UI state.
Not every input requires ngModel.
For a simple action, a template reference variable may be enough.
<input #emailInput type="email">
<button (click)="subscribe(emailInput.value)">
Subscribe
</button>
Component:
subscribe(email: string) {
console.log(email);
}
In this situation, creating a component property solely to hold the current input value may not be necessary.
Incorrect:
<img src="imageUrl">
This uses the literal text imageUrl.
Correct:
<img [src]="imageUrl">
Angular now evaluates the component property.
Incorrect:
<button click="save()">Save</button>
Correct:
<button (click)="save()">Save</button>
Avoid using attr. automatically for every value.
Normal element properties generally use:
<input [value]="name">
Attributes specifically requiring attribute binding use:
<div [attr.aria-label]="description"></div>
Avoid large calculations and complicated expressions such as:
{{ calculateSomethingVeryComplex(data, settings, configuration) }}
Templates are easier to maintain when they mainly describe the view.
Prefer exposing meaningful data from the component:
{{ finalPrice }}
This is syntactically valid:
{{ calculateTotal() }}
But a method used directly in a template may be evaluated repeatedly as Angular updates the view.
For expensive calculations, consider computing or deriving the value more appropriately rather than repeatedly performing substantial work from the template.
Risky:
{{ user.address.city }}
Safer when the object may not yet exist:
{{ user?.address?.city }}
Two-way binding is convenient, but it should not automatically replace clear one-way data flow.
For simple UI display:
<input [value]="name">
may be enough.
For synchronized editable state:
<input [(ngModel)]="name">
may be more appropriate.
Choose the mechanism according to the actual requirement.
Good Angular templates are usually easy to scan without needing to understand large amounts of hidden logic.
Keep templates focused on presentation and interaction.
Prefer:
<p>{{ finalAmount }}</p>
over putting an entire business calculation directly in HTML.
Use meaningful names:
<button (click)="submitOrder()">
Submit Order
</button>
instead of vague method names such as:
<button (click)="doIt()">
Submit Order
</button>
Use class binding when an application state represents a reusable CSS state:
<div [class.invalid]="hasValidationError"></div>
Use template reference variables for small local template interactions:
<input #searchInput>
<button (click)="search(searchInput.value)">
Search
</button>
Use optional chaining where data may legitimately be unavailable:
{{ customer?.address?.city }}
Most importantly, avoid treating the template as a replacement for the component class. The component handles application behavior and state, while the template primarily describes how that state should appear and how the user can interact with it.
| Requirement | Angular Syntax | Example |
|---|---|---|
| Display text | {{ }} | {{ userName }} |
| Bind property | [property] | [src]="imageUrl" |
| Bind attribute | [attr.name] | [attr.aria-label]="label" |
| Bind CSS class | [class.name] | [class.active]="isActive" |
| Bind style | [style.name] | [style.color]="textColor" |
| Handle event | (event) | (click)="save()" |
| Two-way binding | [()] | [(ngModel)]="name" |
| Template reference | #name | #emailInput |
| Optional access | ?. | user?.name |
| Null fallback | ?? | user?.name ?? 'Guest' |
The major symbols can be remembered by the direction of communication:
{{ value }}
Display a value
[property]="value"
Send component data to the template
(event)="action()"
Send an event from the template to the component
[(ngModel)]="value"
Synchronize both directions
#variable
Create a local template reference
object?.property
Safely access a possibly missing value
Once these patterns are understood, reading larger Angular templates becomes much easier because most template interactions are combinations of the same basic mechanisms.
Angular templates extend HTML so that the UI can work directly with application state and user actions.
The goal is not to put application logic inside HTML. A well-designed Angular template clearly represents the component's state, displays the appropriate data, and connects user actions to the component using the simplest suitable binding mechanism.