Templates & Data Binding

Data binding is how a component's TypeScript class and its HTML template stay in sync — values flow from the class into the page, and in some cases back the other way.

Interpolation: displaying a value

Double curly braces drop a class property's value straight into the rendered HTML:

TS profile.component.ts
export class ProfileComponent {
  username = 'jamie99';
  followers = 142;
}
HTML profile.component.html
<p>{{ username }} has {{ followers }} followers.</p>
Rendered output
<p>jamie99 has 142 followers.</p>

Anything inside {{ }} is a small JavaScript-like expression, not just a bare variable — {{ followers * 2 }} or {{ username.toUpperCase() }} both work.

Property binding: setting an element's attribute

Square brackets bind a class value to an element's property — useful for anything interpolation can't reach, like a boolean disabled state or an src that depends on data:

TS button.component.ts
export class ButtonComponent {
  isLoading = true;
}
HTML button.component.html
<button [disabled]="isLoading">Save</button>
Rendered output
<button disabled>Save</button>

[disabled]="isLoading" sets the button's disabled property to whatever isLoading currently evaluates to — true here, so the button renders disabled. If isLoading later changes to false, Angular re-renders the button without needing any manual DOM manipulation.

Two-way binding with ngModel

Combining property and event binding into one syntax, [(ngModel)] keeps a form input and a class property in sync in both directions (requires importing FormsModule):

HTML search.component.html
<input [(ngModel)]="query" placeholder="Search...">
<p>You typed: {{ query }}</p>
Behavior
Typing "angular" into the input immediately updates
the paragraph to read: You typed: angular

The banana-in-a-box syntax [( )] is really shorthand for a property binding plus an event binding at once — it's covered from the event side in the next lesson.

Note: {{ }} interpolation only works for text content between tags, never for attributes — <button disabled="{{ isLoading }}"> doesn't do what it looks like it does, since HTML attributes are always strings and the string "false" is still truthy as an attribute. Use property binding, [disabled]="isLoading", whenever the value needs to stay a real boolean (or number, or object).