EthicsComputerCourses
Join training +91 90532 10052

Templates & Interpolation

Angular · Lesson 5 of 41 Intermediate 6 min read Updated

A template is the HTML of a component, extended with Angular syntax. Plain HTML can only show fixed text; a template can show values from the component class, react to events and repeat or hide parts of the page.

In this lesson you will learn interpolation, the simplest way to print data, and what kinds of expressions you can write inside a template.

Interpolation with {{ }}

Double curly braces print the result of an expression as text. Angular reads the expression in the context of the component instance, so names refer to the class's fields and methods.

TypeScript
import { Component, signal } from '@angular/core';

@Component({
  selector: 'app-bill',
  template: `
    <h2>Bill for {{ student.name }}</h2>
    <p>Items: {{ items().length }}</p>
    <p>Total: ₹{{ price() * quantity() }}</p>
    <p>{{ greet('Meera') }}</p>
  `,
})
export class Bill {
  protected student = { name: 'Farhan' };
  protected items = signal(['Idli', 'Vada', 'Chai']);
  protected price = signal(40);
  protected quantity = signal(3);

  protected greet(name: string) {
    return `Hello, ${name}!`;
  }
}
Output
Bill for Farhan
Items: 3
Total: ₹120
Hello, Meera!

Notice the brackets after items(), price() and quantity(). These fields are signals, and you read a signal by calling it like a function. Plain fields such as student are read without brackets. You will learn signals properly in Signals & computed.

Whenever a signal used in the template changes, Angular updates just the text that depends on it.

What you can write in an expression

Template expressions look like JavaScript, but they are a smaller, safer language. Things you can use:

  • Property access and method calls: student.name, greet('Meera')
  • Arithmetic and comparison: price() * quantity(), marks() >= 33
  • The conditional operator: {{ quantity() > 1 ? 'plates' : 'plate' }}
  • Logical operators &&, ||, ! and nullish coalescing ??
  • Optional chaining ?. for values that may be missing
  • Array and object literals, the exponent operator **, typeof, and untagged template strings with backticks

Here is a second example that uses several of these:

TypeScript
@Component({
  selector: 'app-room-info',
  template: `
    <p>{{ quantity() > 1 ? 'plates' : 'plate' }}</p>
    <p>Room: {{ student.hostel?.room ?? 'Day scholar' }}</p>
    <p>{{ \`Token \${token()} is ready\` }}</p>
  `,
})
export class RoomInfo {
  protected student: { name: string; hostel?: { room: number } } = { name: 'Isha' };
  protected quantity = signal(2);
  protected token = signal(17);
}
Output
plates
Room: Day scholar
Token 17 is ready

student.hostel?.room stops safely and gives undefined when hostel is missing, instead of throwing an error, and ?? then supplies the fallback text. (The backslashes in the third line are only needed because this template is itself inside a TypeScript template string; in a separate .html file you write the backticks and ${} directly.)

What you cannot write

Templates are for displaying data, so some JavaScript is not allowed:

  • Assignments such as count = 5, and ++, --, +=
  • The new keyword, and statements separated by ;
  • Global objects such as Math, window, console or JSON, because only the component's members are in scope

If you try, the build stops. For example:

Output
X [ERROR] TS2339: Property 'Math' does not exist on type 'Bill'.
X [ERROR] NG5002: Parser Error: Bindings cannot contain assignments at column 10 in [ count = 5 ]

When you need such logic, put it in the class (for example a method or a computed signal) and call that from the template.

Local variables with @let

The @let block declares a read-only variable inside a template. It is useful when the same value is needed in several places:

HTML
@let subtotal = price() * quantity();
@let gst = subtotal * 0.05;

<p>Subtotal: ₹{{ subtotal }}</p>
<p>GST (5%): ₹{{ gst }}</p>
<p>Pay: ₹{{ subtotal + gst }}</p>
Output
Subtotal: ₹120
GST (5%): ₹6
Pay: ₹126

A @let value is recalculated whenever the values it uses change. You cannot assign to it again in the template.

Interpolation is safe by default

Interpolation always inserts text, never HTML. If a field holds '<b>Pay at counter</b>', the page shows the angle brackets literally instead of bold text. This automatic escaping protects your app from cross-site scripting (XSS), an attack where someone sneaks a script into data that a page later displays.

Some characters have special meaning in templates. To show a literal curly brace, write {{ '{' }} or the HTML entity &#123; (and &#125; for }). If the compiler ever reads an @ in your text as the start of a block, write it as &#64;.

Keep expressions quick

Angular evaluates template expressions often, every time it checks the component. Expressions should be fast and must not change anything (no side effects). Calling a method that loops over thousands of items or makes an HTTP request in a template slows the app down and can cause bugs. Use a computed signal for derived values; it only recalculates when its inputs change.

Common mistakes

  • Forgetting the brackets on a signal. {{ price }} does not print the number, and the compiler warns: NG8109: price is a function and should be invoked: price(). Write {{ price() }}.
  • Making template-only members public. Mark them protected so the template can use them but other classes cannot.
  • Putting business logic in templates. Long conditions in {{ }} are hard to read and test. Move them to the class.
  • Trying to render HTML strings with interpolation. It shows the tags as text, on purpose. Build the structure in the template instead.

Key points

  • {{ expression }} prints the result of an expression as text, using the component's members.
  • Read signals by calling them: {{ total() }}; read plain fields without brackets.
  • Expressions support operators, ?., ??, the conditional operator and template strings, but not assignments, new or globals such as Math.
  • @let name = expression; creates a read-only local variable in the template.
  • Interpolation escapes HTML automatically, which protects against XSS.

Exercise

Create a component ResultCard with signals studentName ("Rohan"), marks (412) and maxMarks (500). In the template, show the name, the marks as "412 / 500", the percentage using a @let variable, and the word "Pass" or "Fail" (pass is 33% or more). Do the rounding of the percentage in a class method, not with Math in the template.

Show solution
TypeScript
import { Component, signal } from '@angular/core';

@Component({
  selector: 'app-result-card',
  template: `
    @let percent = toPercent(marks(), maxMarks());
    <h2>{{ studentName() }}</h2>
    <p>Marks: {{ marks() }} / {{ maxMarks() }}</p>
    <p>Percentage: {{ percent }}%</p>
    <p>Result: {{ percent >= 33 ? 'Pass' : 'Fail' }}</p>
  `,
})
export class ResultCard {
  protected studentName = signal('Rohan');
  protected marks = signal(412);
  protected maxMarks = signal(500);

  protected toPercent(got: number, max: number) {
    return Math.round((got / max) * 1000) / 10;
  }
}

The page shows Percentage: 82.4% and Result: Pass. Math is fine inside the class, where normal TypeScript rules apply.

Quick Quiz

1. How do you print the value of a signal called total in a template?

2. Which of these is NOT allowed in a template expression?

3. A field contains '<i>Hi</i>'. What does {{ field }} show?

4. What does @let gst = subtotal * 0.05; do?

Learn Angular with a mentor

Free lessons get you started. Our Full Stack Web Development training adds real projects and code reviews from working developers.

  • Project-based learning
  • Mentor code reviews
  • Free counselling call