Angular Data Binding
Data binding connects your component's state to the template.
Data Binding Essentials
- Connect component state and template markup.
- Useinterpolation for text,property binding for DOM properties, andevent binding for user actions.
- Usetwo-way binding for form inputs that both display and update state.
- Bind attributes with
[attr.*], and classes/styles with[class.*]/[style.*].
{{ value }}[prop]="value"(event)="handler($event)"[(ngModel)]="value"Notes:
- Related: SeeTemplates for interpolation basics,Events for handling user input, andConditional Rendering to show/hide content based on state.
- For two-way binding with
ngModel, importFormsModule.
Basic Data Binding
Interpolation:{{ value }}prints text.Property binding:[prop]="value"sets element/DOM properties.Event binding:(event)="handler($event)"listens to user actions.
{{ name }}[value]="name"(input)="name = $any($event.target).value"Example
Bind values and handle events to keep the view in sync with component state:
Example
import { bootstrapApplication } from '@angular/platform-browser';import { Component } from '@angular/core';@Component({ selector: 'app-root', standalone: true, template: ` <h3>Data Binding</h3> <input [value]="name" (input)="name = $any($event.target).value" placeholder="Type your name"> <p>Hello {{ name }}!</p> <button (click)="count = count + 1">Clicked {{ count }} times</button> <button [disabled]="isDisabled">Can't click me</button> `})export class App { name = 'Angular'; count = 0; isDisabled = true;}bootstrapApplication(App);<app-root></app-root>Example explained
{{ name }}: Interpolation prints the currentnamevalue as text.[value]="name": Property binding sets the input's value from the component state.(input)="name = $any($event.target).value": Event binding updatesnamefrom the input's current text.(click)="count = count + 1": Increments thecountfield when the button is clicked.[disabled]="isDisabled": Disables the button whenisDisabledis true.
Notes:
Keep expressions light:Avoid heavy work in{{ ... }}; compute in the component.No side effects:Don't mutate state or call state-changing functions inside bindings.Accessibility:If you disable elements, communicate why (e.g., helper text or ARIA) so users aren't confused.
Two-way Binding
- Sync template and component: page ↔ component.
- Use
[(ngModel)]for form controls. - Conceptually equals
[value]+(input). - Requires
FormsModule.
<input [(ngModel)]="name">Example
Use[(ngModel)] to read and update form values:
Example
import { bootstrapApplication } from '@angular/platform-browser';import { Component } from '@angular/core';import { CommonModule } from '@angular/common';import { FormsModule } from '@angular/forms';@Component({ selector: 'app-root', standalone: true, imports: [CommonModule, FormsModule], template: ` <h3>Two-way Binding (ngModel)</h3> <label> Name: <input [(ngModel)]="name" placeholder="Type your name" /> </label> <label> Favorite: <select [(ngModel)]="favorite"> <option value="Angular">Angular</option> <option value="TypeScript">TypeScript</option> <option value="JavaScript">JavaScript</option> </select> </label> <p>Hello {{ name || 'friend' }}!</p> <p>Favorite: {{ favorite }}</p> `})export class App { name = 'Angular'; favorite = 'Angular';}bootstrapApplication(App);<app-root></app-root>Example explained
[(ngModel)]="name": Two-way binds the input to thenamefield (requiresFormsModule).[(ngModel)]="favorite": Keeps theselectand thefavoritefield in sync.- Concept: Equivalent to
[value]plus(input)wiring under the hood.
Note:[(ngModel)] won't work unlessFormsModule is imported.
Attribute Binding
- Some values are attributes, not DOM properties (e.g.,
colspan). - Use
[attr.*]when no property exists. - Use
[class.*]and[style.*]for classes and styles.
[attr.colspan]="span"[class.active]="isActive"[style.color]="color"Example
Bind attributes, classes, and styles from component state:
Example
import { bootstrapApplication } from '@angular/platform-browser';import { Component } from '@angular/core';import { CommonModule } from '@angular/common';@Component({ selector: 'app-root', standalone: true, imports: [CommonModule], styles: [` table { border-collapse: collapse; margin-top: 10px; } th, td { border:1px solid #ccc; padding:8px 10px; } .toolbar { display:flex; gap:10px; align-items:center; } `], template: ` <h3>Attribute Binding (attr.*)</h3> <div> <label>Colspan: <input type="range" min="1" max="3" [value]="span" (input)="span = +$any($event.target).value"> {{ span }}</label> <label>Title: <input [value]="title" (input)="title = $any($event.target).value"></label> </div> <table [attr.title]="title"> <thead> <tr><th>A</th><th>B</th><th>C</th></tr> </thead> <tbody> <tr> <td [attr.colspan]="span">colspan={{ span }}</td> <td *ngIf="span < 2">B</td> <td *ngIf="span < 3">C</td> </tr> </tbody> </table> `})export class App { span = 1; title = 'Data table';}bootstrapApplication(App);<app-root></app-root>Example explained
[attr.title]="title": Sets the table'stitleattribute from thetitlefield.[attr.colspan]="span": Binds the cell'scolspanattribute to the number inspan.- Range input: Adjusts
spanby reading$event.target.value; the template reflects the change. - Conditional cells:
*ngIfshows/hides extra columns based on the currentspan.
Note: Use property binding when available; use[attr.*] only when no property exists (e.g.,colspan).

