Component Binding
-
Binding in Angular is the automatic
synchronization of databetween the component class and thetemplate, -
It keeps your UI in sync with your application state.
-
It connects your TypeScript logic with your HTML view through various syntaxes
- like
{{ }},[ ], and( ).
- like
| Biding | Name. | Example |
|---|---|---|
{{ }} | Interpolation | {{ title }} |
[ ] | Property | [disabled]="isLoading" |
( ) | Event | (click)="onSave()" |
ngModel | Two way | <input [(ngModel)]="username" /> |
1. Interpolation Binding
Section titled “1. Interpolation Binding”Syntax: {{ expression }}
Display component data in templates
<h1>{{ title() }}</h1><p>Welcome, {{ user().name }}!</p><div>Total: {{ total() }}</div><span>{{ items().length }} items</span>title = signal("My App");user = signal({ name: "John", age: 30 });items = signal([1, 2, 3]);total = computed(() => this.items().reduce((sum, item) => sum + item, 0));2. Property Binding
Section titled “2. Property Binding”Syntax: [property]="expression" or bind-property="expression"
Set element properties, directives, and component inputs
Element Properties
Section titled “Element Properties”<img [src]="imageUrl()" [alt]="imageAlt()" /><button [disabled]="isLoading()">Save</button><div [class.active]="isActive()"></div><input [value]="username()" />Component Inputs
Section titled “Component Inputs”<app-user [user]="currentUser()" [isAdmin]="true"></app-user>// Child component using modern inputsuser = input<User>();isAdmin = input<boolean>(false);3. Event Binding
Section titled “3. Event Binding”Syntax: (event)="handler()" or on-event="handler()"
Respond to DOM events and component outputs
DOM Events
Section titled “DOM Events”<button (click)="onSave()">Save</button><input (input)="onInput($any($event).target.value)" /><form (submit)="onSubmit($event)" (keydown.enter)="onEnter()"></form>Component Outputs
Section titled “Component Outputs”<app-user (userSaved)="onUserSaved($event)" (cancel)="onCancel()"></app-user>// Child component using modern outputsuserSaved = output<User>();cancel = output<void>();4. Two-Way Binding
Section titled “4. Two-Way Binding”Syntax: [(ngModel)]="property" or [(property)]="value"
Combine property and event binding for two-way data flow
Traditional with FormsModule
Section titled “Traditional with FormsModule”<input [(ngModel)]="username" /><select [(ngModel)]="selectedOption"> <option value="1">One</option> <option value="2">Two</option></select>username = "";selectedOption = "1";Custom Two-Way Binding
Section titled “Custom Two-Way Binding”Traditional:
<app-search [(query)]="searchTerm"></app-search>// Child component@Input() query: string = '';@Output() queryChange = new EventEmitter<string>();Modern:
<app-search [(query)]="searchTerm"></app-search>// Child component - modern approachquery = input<string>("");queryChange = output<string>();5. Attribute Binding
Section titled “5. Attribute Binding”Syntax: [attr.attribute]="expression"
Set HTML element attributes (not properties)
<td [attr.colspan]="colSpan">Content</td><button [attr.aria-label]="buttonLabel">Action</button><div [attr.data-id]="itemId"></div><img [attr.src]="imagePath" [attr.alt]="description" />6. Class Binding
Section titled “6. Class Binding”Syntax: [class.class-name]="condition"
Conditionally apply CSS classes
<div [class.active]="isActive()" [class.disabled]="isDisabled()" [class.loading]="isLoading()"> Content</div>7. Style Binding
Section titled “7. Style Binding”Syntax: [style.property]="expression"
Set inline styles dynamically
<div [style.color]="textColor()" [style.font-size.px]="fontSize()" [style.width.%]="widthPercent()" [style.background-color]="bgColor()"> Styled content</div>8. Template Reference Variables
Section titled “8. Template Reference Variables”Syntax: #variableName or ref-variableName
Reference elements in template
<input #emailInput type="email" /><button (click)="focusInput(emailInput)">Focus</button>
<app-user #userComp></app-user><div>{{ userComp.user?.name }}</div>Modern Angular Approach (Angular 16+)
Section titled “Modern Angular Approach (Angular 16+)”1. Signal-based Bindings
Section titled “1. Signal-based Bindings”Reactive Properties with Signals:
@Component({ template: ` <h1>{{ title() }}</h1> <button [disabled]="isLoading()" (click)="loadData()"> {{ isLoading() ? "Loading..." : "Load Data" }} </button>
@for (item of items(); track item.id) { <div [class.active]="selectedItemId() === item.id" (click)="selectItem(item.id)" > {{ item.name }} </div> } `,})export class ModernComponent { // Signal-based state title = signal("Modern Angular"); isLoading = signal(false); items = signal<Item[]>([]); selectedItemId = signal<number | null>(null);
// Computed values activeItem = computed(() => this.items().find((item) => item.id === this.selectedItemId()) );
// Methods async loadData() { this.isLoading.set(true); const data = await fetchData(); this.items.set(data); this.isLoading.set(false); }
selectItem(id: number) { this.selectedItemId.set(id); }}2. Modern Input/Output API
Section titled “2. Modern Input/Output API”Child Component:
@Component({ selector: "app-user-card", standalone: true, template: ` <div [class.admin]="isAdmin()"> <h3>{{ user().name }}</h3> <p>Email: {{ user().email }}</p> <button (click)="onEdit.emit(user().id)">Edit</button> <button (click)="onDelete.emit(user().id)">Delete</button> </div> `,})export class UserCardComponent { // Modern input API user = input.required<User>(); isAdmin = input<boolean>(false);
// Modern output API onEdit = output<number>(); onDelete = output<number>();}Parent Component:
@Component({ standalone: true, imports: [UserCardComponent], template: ` <app-user-card [user]="selectedUser()" [isAdmin]="currentUser().role === 'admin'" (onEdit)="editUser($event)" (onDelete)="deleteUser($event)" > </app-user-card> `,})export class ParentComponent { selectedUser = signal<User>({ id: 1, name: "John", email: "john@example.com", }); currentUser = signal({ role: "admin" });
editUser(userId: number) { // Handle edit }
deleteUser(userId: number) { // Handle delete }}3. New Control Flow with Binding
Section titled “3. New Control Flow with Binding”Modern Template Syntax:
@if (isLoading()) {<div class="loading">Loading...</div>} @else if (items().length > 0) {<ul> @for (item of items(); track item.id) { <li [class.selected]="selectedItem() === item" (click)="selectedItem.set(item)" > {{ item.name }} </li> }</ul>} @else {<p>No items found</p>} @for (user of users(); track user.id; let i = $index) {<app-user-card [user]="user" [style.order]="i" (onDelete)="removeUser($event)"></app-user-card>}4. Model Inputs (Two-way Binding Modern)
Section titled “4. Model Inputs (Two-way Binding Modern)”Modern Two-way Binding:
@Component({ selector: "app-toggle", template: ` <button [class.active]="value()" (click)="valueChange.emit(!value())"> {{ value() ? "On" : "Off" }} </button> `,})export class ToggleComponent { value = input<boolean>(false); valueChange = output<boolean>();}Usage:
<app-toggle [(value)]="isEnabled" /><p>Status: {{ isEnabled() ? 'Enabled' : 'Disabled' }}</p>Key Benefits of Modern Approach
Section titled “Key Benefits of Modern Approach”- Automatic Reactivity: Signals trigger updates automatically
- Better Type Safety: Enhanced generics and type inference
- Reduced Boilerplate: Less code for common patterns
- Improved Performance: Granular change detection
- Modern Syntax: Cleaner, more intuitive template syntax
The modern approach maintains all binding types while making them more reactive, type-safe, and performant through signals and the new template syntax.