Angular data binding: interpolation, property/attribute/class/style, events, and two-way ([(...)])

LowIntermediateAngular
Preparing for interviews?

Use guided tracks for structured prep, then practice company-specific question sets when you want targeted interview coverage.

Quick Answer

Data binding is how Angular connects component state (TS) to the template (HTML) and back. It’s mostly one-way (component ➜ view via interpolation/property bindings, view ➜ component via event bindings). Two-way binding is optional syntactic sugar that combines both directions (commonly via forms/ngModel or custom @Input/@Output pairs).

Answer

Core idea

Angular templates are declarative. You bind values into the DOM and bind events back into the component. Angular then keeps the DOM synced by re-running the template update phase during change detection (triggered by events, async work, input changes, etc.).

Binding kind

Direction

What it binds to

Syntax

Example

Interpolation

Component ➜ View

Text nodes / attribute text

{{ expr }}

Hello {{ user.name }}

Property binding

Component ➜ View

DOM properties (not HTML attributes)

[prop]="expr"

<button [disabled]="loading">Save</button>

Attribute binding

Component ➜ View

HTML attributes (incl. ARIA, non-property attrs)

[attr.name]="expr"

<div [attr.aria-label]="label"></div>

Class binding

Component ➜ View

CSS classes

[class.foo]="expr"

<li [class.active]="isActive">...</li>

Style binding

Component ➜ View

Inline styles (+ units)

[style.width.px]="n"

<div [style.opacity]="alpha"></div>

Event binding

View ➜ Component

DOM events or child @Output

(event)="stmt"

<input (input)="onInput($event)">

Two-way binding

Both

Property + event (banana-in-a-box)

[(x)]="expr"

<input [(ngModel)]="name">

Angular binding types you’re expected to know in interviews (including attr/class/style prefixes).

Property vs Attribute (common interview trap)

[disabled] sets the DOM property (actual runtime behavior). [attr.disabled] sets/removes the HTML attribute string. For ARIA and many “string-only” attributes, you typically use [attr.*]. For real element state, use property binding.

HTML
<h2>{{ title }}</h2>

<img [src]="avatarUrl" [alt]="userName" />

<button type="button" [disabled]="isSaving" (click)="save()">
  Save
</button>

<input
  [value]="query"
  (input)="query = ($event.target as HTMLInputElement).value"
  [attr.aria-label]="'Search'"
/>

<div [class.error]="hasError" [style.width.px]="panelWidth"></div>
                  

Two-way binding is just sugar

[(x)] expands to [x] + (xChange) for custom components. In forms, [(ngModel)] is provided by template-driven forms (requires importing FormsModule).

TYPESCRIPT
import { Component, EventEmitter, Input, Output } from '@angular/core';

@Component({
  selector: 'app-rating',
  template: `
    <button type="button" (click)="set(1)">1</button>
    <button type="button" (click)="set(2)">2</button>
    <button type="button" (click)="set(3)">3</button>
    <span>Current: {{ value }}</span>
  `
})
export class RatingComponent {
  @Input() value = 0;
  @Output() valueChange = new EventEmitter<number>();

  set(v: number) {
    this.valueChange.emit(v);
  }
}

// parent template usage:
// <app-rating [(value)]="rating"></app-rating>
// expands to:
// <app-rating [value]="rating" (valueChange)="rating = $event"></app-rating>
                  

What makes the UI update?

Interview-safe answer

User events

Template events run handlers, state changes, then Angular checks affected views.

Async work (HTTP/timers/observables/promises)

Angular typically schedules change detection (Zone-based apps) or you trigger it explicitly in zoneless setups.

Parent input changes

When parent re-renders and updates an input binding, child updates in the next check.

Data binding + change detection are inseparable: bindings update during change detection passes.

Common pitfall

What goes wrong

Fix

Heavy expressions in templates

They run often during change detection and can cause jank

Move work to TS and bind to a field/signal/observable result

No FormsModule but using [(ngModel)]

Template compile/runtime errors

Import FormsModule (or use Reactive Forms)

Using attribute binding for real element state

[attr.disabled] doesn’t behave like [disabled] in all cases

Prefer property binding for element state

Trying to use two-way binding everywhere

Harder to reason about state flow in complex apps

Prefer one-way data flow + explicit events; use two-way mainly for form-like controls

These are the things seniors call out quickly.

Summary

Data binding connects TS state and HTML templates; Angular syncs the DOM via change detection.

Know the full surface area: interpolation, property, attr/class/style, event, and two-way binding.

Two-way binding is syntactic sugar: [(x)] = [x] + (xChange).

Interview nuance: property vs attribute binding, and when to use [attr.*], [class.*], [style.*].

Similar questions
Guides
10 / 37