AcademyAngular
Interpolation and Property Binding
{{ }} renders text; [prop] sets a DOM property directly. The same distinction as textContent vs. a property assignment, and it decides which one a template needs.
2 min readUpdated 3 exercises
{{ }} is shorthand for a text-node binding
{{ expression }} only ever produces a string, inserted as a text node. It looks like it can go anywhere, but it cannot set a boolean property, cannot set a whole object onto an input, and silently stringifies anything that is not already text:
<h2>{{ user.title }}</h2>
<!-- {{ user }} would render "[object Object]" -->That last line is a real bug shape, not a hypothetical one: interpolating the object instead of the field it holds compiles fine and renders garbage, because JavaScript's default toString() is the only thing standing between the template and the console.
[prop] sets the DOM property, not the HTML attribute
Property binding writes to the element's DOM property directly, which is why it accepts any expression type — a boolean, a number, an object — not just a string:
<img [src]="user.avatarUrl" [alt]="user.name" />
<button [disabled]="isSaving">Save</button>This is the one every candidate has to unlearn from plain HTML: disabled="false" as a bare attribute still disables the button, because HTML attributes are presence-based — the string "false" is still a truthy presence. [disabled]="false", in square brackets, binds to the actual boolean property and behaves the way false should. The same trap catches src: interpolating a broken expression into a plain src="{{ user.avatarUrl }}" attribute still issues a request for whatever string comes out, dead link included, while [src] at least binds to the property Angular's change detection actually tracks.
Attribute binding exists for the cases property binding cannot cover
A handful of things genuinely are not DOM properties — colspan, ARIA attributes, aria-label — and for those, [attr.colspan] sets the attribute explicitly rather than a nonexistent property of the same name. Reaching for [attr.x] on something that does have a property (like disabled or src) works but is the wrong tool: it round-trips through the DOM's string-based attribute layer instead of the typed property Angular already exposes.
What interviewers check
Whether the distinction between an attribute and a property is something you can state precisely rather than gesture at, and whether you notice a "disabled button that won't disable" or a "broken image that never updates" for what it actually is: a plain attribute holding a stringified expression where a property binding belongs.
Now practice it
1 quiz · 2 drillsReading this page is the cheap half. These are the exercises that make you use it.
- Interpolation & Property BindingFix a profile card that interpolates a whole object instead of a field, and binds a dead avatar and a stuck disabled button as strings instead of properties.DrillSolve · EasyDrillSolve · Easy
- Class & Style BindingsThe same [prop] mechanics applied to class and style, on a task list whose "done" styling and priority bar never react to the data.DrillSolve · EasyDrillSolve · Easy
- Fundamentals · Angular BasicsBasics questions on templates and bindings — the foundation every other Angular topic on this page assumes.QuizTake · EasyQuizTake · Easy
Read next
Compound Components and Dynamic Outlets
A compound component's parts coordinate through a shared, injected service instead of local state; NgComponentOutlet renders whichever component a mapping picks at runtime.
2 min
Control Flow: @if and @for
Angular 17+ replaced *ngIf and *ngFor with built-in @if and @for blocks — faster, stricter about tracking, and no CommonModule import required.
2 min