Data Binding

Chapter 3
Data Binding — Property, Event, and Two-Way Binding
Connecting a component's class properties to its template in both directions

Interpolation ({{ value }}, Chapter 2) only inserts text content. Angular has three more binding forms covering everything else — setting a DOM property directly, responding to events, and the special case of keeping a form field and a class property in sync automatically.

Property Binding — [property]="expression"

<button [disabled]="isSaving">Save</button> <img [src]="photoUrl" />

Square brackets around an attribute name — [disabled], [src] — bind that DOM property directly to a class property or expression, evaluated as real TypeScript/JavaScript rather than treated as a plain string. [disabled]="isSaving" sets the button's actual disabled property to whatever isSaving currently is (a real boolean) — the same underlying need as React's curly-brace rule for non-string prop values (Fundamentals Chapter 2), just expressed with brackets instead.

Event Binding — (event)="handler()"

// counter.component.ts @Component({ selector: 'app-counter', standalone: true, template: ` <p>Count: {{ count }}</p> <button (click)="increment()">+1</button> `, }) export class CounterComponent { count = 0; increment() { this.count++; } }

Parentheses around an event name — (click) — call the given expression whenever that event fires, the direct equivalent of React's onClick={handler}. increment() is a regular method on the class; this.count++ updates the property directly — there's no separate setter function the way useState requires, since Angular's change detection automatically re-renders the template after any event handler runs.

Accessing the Event Object — $event

<input (input)="onInput($event)" />
onInput(event: Event) { const value = (event.target as HTMLInputElement).value; console.log(value); }

$event is a special template variable holding the actual DOM event object — passing it explicitly to the handler is the same idea as React's automatic event-object argument (Fundamentals Chapter 4), just opted into rather than implicit. The as HTMLInputElement cast is TypeScript-specific: event.target is typed generically as EventTarget, so accessing its .value property requires telling the compiler exactly what kind of element it actually is.

Two-Way Binding — [(ngModel)]

// requires FormsModule, imported directly into the component import { FormsModule } from '@angular/forms'; @Component({ selector: 'app-name-form', standalone: true, imports: [FormsModule], template: ` <input [(ngModel)]="name" /> <p>Hello, {{ name }}!</p> `, }) export class NameFormComponent { name = ''; }

[(ngModel)]="name" — sometimes called "banana in a box," combining property binding's square brackets with event binding's parentheses — keeps the input's value and the name property synchronized automatically in both directions: typing updates name, and changing name elsewhere in code updates the input. This is the same end result as React's controlled input pattern (value + onChange, Fundamentals Chapter 7), collapsed into one directive instead of two explicit bindings.

ngModel needs FormsModule imported — every time
[(ngModel)] only works once FormsModule is added to the component's own imports array — forgetting it produces a template compile error about ngModel not being a known property, the same category of "unrecognized" error from Chapter 2's missing-component-import warning, just for a built-in directive instead of a custom component this time.

Class and Style Bindings

<div [class.active]="isActive">...</div> <div [style.color]="isError ? 'red' : 'black'">...</div>

[class.active] toggles a single CSS class on or off based on a boolean expression, and [style.color] binds one specific inline style property directly — the same conditional-styling need React handles with a template literal or object passed to className/style (Fundamentals Chapter 5).

AngularReact equivalent
{{ value }}{value}
[property]="expr"property={expr}
(event)="handler()"onEvent={handler}
[(ngModel)]="prop"value={prop} onChange={...}

Coding Challenges

Challenge 1

Build a component with a boolean isLocked property and a button whose disabled state is property-bound to it, plus a second button (event-bound) that toggles isLocked.

📄 View solution
Challenge 2

Build a click counter component using event binding, with separate +1, -1, and Reset buttons, matching the equivalent React counter from Fundamentals Chapter 3.

📄 View solution
Challenge 3

Build a component with a text input two-way bound via ngModel to a name property, displaying "Hello, [name]!" live below it as the user types. Remember FormsModule.

📄 View solution

Chapter 3 Quick Reference

  • [property]="expr" — binds a real DOM property directly, not a plain string
  • (event)="handler()" — calls an expression when that event fires
  • $event — the actual event object, passed explicitly to a handler when needed
  • [(ngModel)]="prop" — two-way binding; requires FormsModule in the component's imports
  • [class.x] / [style.y] — bind a single class or style property conditionally
  • No setter function needed — Angular's change detection re-renders after any event handler runs automatically
  • Next chapter: built-in directives — *ngIf, *ngFor, ngClass, ngStyle