Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Template Syntax and Lifecycle  ›  Capstone Project

@let and @defer

@defer 15 min@let names a read-only value inside a template so it is written once, and @defer postpones loading a part of the template, with its code, until a trigger such as the element scrolling into view.

@let and @defer

The plant details page has two problems. The expression plant().everyDays - daysSince() appears three times, and a heavy GrowthChart at the very bottom slows every visit, even though most people never scroll that far. Two small blocks fix both.

The rule

@let names a value once; @defer loads a piece only when it is needed.

@let declares a named value inside a template:

@let daysLeft = plant().everyDays - daysSince();

<h2>{{ plant().name }}</h2>
@if (daysLeft <= 0) {
  <p class="alert">Water today!</p>
} @else {
  <p>Next watering in {{ daysLeft }} days.</p>
}

The value updates whenever the signals it reads change. It is read-only: you cannot assign to it from a template statement. It is visible only after its declaration, within the same block and blocks nested inside it. Note the closing semicolon.

@defer delays part of a template:

@defer (on viewport) {
  <app-growth-chart [plant]="plant()" />
} @placeholder {
  <p>Growth chart</p>
} @loading (minimum 300ms) {
  <p>Loading chart…</p>
} @error {
  <p>The chart could not load.</p>
}

At build time, Angular moves GrowthChart's code into a separate file. The page ships without it; the file downloads only when the trigger fires. Until then, @placeholder shows. While downloading, @loading shows. If it fails, @error shows.

Common triggers:

  • on idle (the default): when the browser is idle.
  • on viewport: when the placeholder scrolls into view.
  • on interaction or on hover: when the user clicks or hovers the placeholder.
  • on timer(2s), on immediate, or when someCondition().

For the code to be split out, a deferred component must be standalone and not used anywhere else in the same template file.

The shortcut

For @let, the test is "did I write this expression twice?" Name it once. For @defer, the test is "does every visitor need this the moment the page opens?" If not, and it is heavy, defer it on the trigger that matches when people actually reach it.

Deciding what to defer on the plant pageStep 1 of 4
  1. Plant name and watering status

    Everyone needs them immediately. Keep them normal.

Drills

Answer fast — trust the rule.

quick drill

What is the default trigger when you write @defer with no trigger?

quick drill

Which block shows while the deferred content has not yet been triggered?

quick drill

What is true about @let total = plants().length;?

quick drill

Why might a deferred GrowthChart still load with the rest of the page?

Remember

  • @let name = expr; names a read-only value, visible after its declaration.
  • @defer (trigger) { } @placeholder { } @loading { } @error { } splits heavy parts out; default trigger is on idle.
  • Trap: using the deferred component elsewhere in the template keeps it in the main bundle.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainA chart that loads when needed

The Greenhouse plant page ends with a heavy GrowthChart component that most visitors never scroll to. The page also repeats plant().everyDays - daysSince() in three places. Write the template changes using @let and @defer, and explain what each gains and one rule each must follow.