@defer is Angular’s template block for lazily loading and rendering view content according to conditions, interactions, viewport visibility, or application idleness. It replaces much of the boilerplate and inflexibility of earlier component-lazy-loading patterns. section 10.2
A basic block separates a standalone component into its own JavaScript bundle. With no clause, Angular begins loading it when the page is visited; conditional triggers can postpone that work further. section 10.2.1 section 10.2.2
Choose a trigger that matches when the deferred content becomes useful:
- Use `when` with a Boolean condition, such as opening a confirmation dialog; combine it with `@if` when the content must later be removed. section 10.2.2
- Use `on interaction` for a click or keydown event, or `on hover` when pointer movement should initiate loading. section 10.2.2
- Use `on viewport` for content that should load as it becomes visible, such as a footer lower on the page. section 10.2.2
- Use the default idle behavior to load deferred content when animations, painting, and current HTTP requests are no longer active. section 10.2.2
Employee deletion confirmation
An employee list can expose a Delete button and defer its confirmation dialog until `on interaction(deleteButton)` fires. A viewport block can similarly defer the HRMS footer, using `@placeholder` content so Angular has an element to observe before the footer loads. section 10.2.2
Listing 10.10 Deferring a component until a UI interaction
<h2>Employee List</h2>
<table>
<thead>
<tr>
<th>Full Name</th>
<th>Position</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let employee of employees$ | async">
<td>
<img [ngSrc]="employee.profilePicture" width="20" height="20" />
<a [routerLink]="['/employees/details', employee.id]">
{{ employee.firstName }} {{ employee.lastName }}
</a>
</td>
<td appTruncate [limit]="10">{{ employee.position }}</td>
<td>
<button (click)="isConfirmationOpen = true" #deleteButton> #1
Delete
</button>
@defer (on interaction(deleteButton)) { #2
<app-confirmation-dialog
[isConfirmationOpen]="isConfirmationOpen"
/>
}
</td>
</tr>
</tbody>
</table>
Shows the interaction-triggered confirmation dialog pattern. section 10.2.2
Listing 10.12 Deferring a component with a placeholder
<app-header/>
<router-outlet></router-outlet>
@defer (on viewport) {
<app-footer/>
} @placeholder { #1
<div>Footer</div> #2
}
Shows placeholder content supporting a viewport-triggered footer. section 10.2.2
Only standalone components can actually be deferred into separate loading units. Non-standalone components may appear inside the block, but their NgModules determine how they load. Deferred blocks can also provide placeholder, loader, and error content, with prefetching and trigger customization available. section 10.2.1 section 10.5
