What are template expressions?
A template expression in Angular produces a value similar to any JavaScript expression. Angular executes the expression during change detection and assigns the computed result to a property of a binding target—such as an HTML element attribute, a component @Input(), or a directive property.
1. Common Template Expression Usages
- Property Binding (
[property]="expression"):
<button [disabled]="isSubmitting || !userForm.valid">Save Changes</button>
<img [src]="userProfile.avatarUrl" [alt]="userProfile.displayName" />
- Interpolation (
{{ expression }}):
<h3>{{ user.firstName + ' ' + user.lastName }}, welcome to Angular!</h3>
2. Prohibited JavaScript Expressions in Template Expressions
Angular deliberately restricts template expressions to keep templates declarative, secure, idempotent, and free of side effects. Template expressions must not alter application state because expressions are evaluated repeatedly on change detection cycles.
| Prohibited Syntax | Example | Reason for Prohibition |
|---|---|---|
| Assignments | count = 5, user.name = 'John', a += 1 | Violates unidirectional data flow; causes ExpressionChangedAfterItHasBeenCheckedError. |
| Object Instantiation | new Date(), new UserService() | Creates new object references on every render pass, destroying memoization and triggering infinite change detection loops. |
| Chaining Operators | ; (semicolon) or , (comma) | Templates should not execute sequences of imperative statements. |
| Increment / Decrement | count++, --total | Modifies variable state during rendering (unintended side effect). |
| Bitwise Operators | a | b, x & y | Ambiguous conflict with Angular template pipe syntax (|). |
[!NOTE] Idempotence & Purity: Angular template expressions should be idempotent—invoking the expression multiple times with identical inputs must return the exact same result without mutating application state. If an expression alters a component property during evaluation, Angular's change detection throws
ExpressionChangedAfterItHasBeenCheckedErrorin development mode.
3. Allowed vs Prohibited Syntax Comparison
<!-- ✅ VALID: Pure, idempotent evaluation -->
<div [class.active]="selectedTab === 'profile'">
<span>Balance: {{ formatCurrency(account.balance) }}</span>
<p>Items: {{ items.length > 0 ? items.join(', ') : 'None' }}</p>
</div>
<!-- ❌ INVALID: Prohibited syntax causes compile-time Template parse error -->
<!-- <div [title]="currentCount++"></div> -->
<!-- <span>{{ new Date().toLocaleTimeString() }}</span> -->
<!-- <button [disabled]="status = 'pending'"></button> -->