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

The Component Lifecycle

Component Lifecycle 15 minAngular calls lifecycle hooks at fixed moments in a component's life, so setup that needs inputs goes in ngOnInit, work that needs the rendered view waits for the view, and cleanup goes in ngOnDestroy.

The Component Lifecycle

PlantTimer shows "watered 3 hours ago" and ticks every minute. It needs its plant before it can start, and it must stop ticking when the user leaves the page. Angular tells a component when these moments arrive through lifecycle hooks: methods it calls at fixed points.

The rule

Construct to exist, init to start, destroy to clean up.

The main hooks, in the order Angular calls them:

Hook When Typical use
constructor Class created Inject services; nothing else
ngOnChanges An input changed (also before init) React to new input values
ngOnInit Once, after the first inputs are set Start work that needs inputs
ngAfterViewInit Once, after the template and children render Touch elements found by viewChild
ngOnDestroy Just before removal Stop timers, release resources

There are also ngDoCheck, ngAfterContentInit, ngAfterContentChecked and ngAfterViewChecked for rarer cases.

import { Component, OnDestroy, OnInit, input, signal } from '@angular/core';

@Component({
  selector: 'app-plant-timer',
  template: `<p>Watered {{ minutesAgo() }} minutes ago</p>`,
})
export class PlantTimer implements OnInit, OnDestroy {
  plant = input.required<Plant>();
  minutesAgo = signal(0);
  private timerId = 0;

  ngOnInit() {
    this.tick();
    this.timerId = setInterval(() => this.tick(), 60_000);
  }

  ngOnDestroy() {
    clearInterval(this.timerId);
  }

  private tick() {
    const ms = Date.now() - this.plant().lastWatered.getTime();
    this.minutesAgo.set(Math.floor(ms / 60_000));
  }
}

Implementing the OnInit and OnDestroy interfaces is optional, but it lets TypeScript catch a misspelled hook name.

Signal-era helpers cover the same moments: inject(DestroyRef).onDestroy(...) registers cleanup from anywhere, and afterNextRender(...) runs code once the browser has drawn the component.

The shortcut

Sort every piece of setup code by what it needs. Needs only services? Constructor. Needs inputs? ngOnInit. Needs rendered elements? After the view. Starts something that keeps running? Pair it with cleanup straight away.

Placing PlantTimer's codeStep 1 of 4
  1. Inject the clock service

    Needs nothing but DI, so the constructor (or a field with inject).

The trap is reading a required input in the constructor. It is not set yet, and a signal input throws an error saying it has no value.

Drills

Answer fast — trust the rule.

quick drill

Which hook runs first after the constructor when a component has inputs?

quick drill

Where should you start work that needs the plant input?

quick drill

A component starts setInterval but never clears it. What happens when it is removed?

quick drill

When is an element found with viewChild first safe to use in the lifecycle hooks?

Remember

  • Constructor to exist, ngOnInit to start, ngOnDestroy to clean up.
  • Sort code by what it needs: services, inputs or rendered elements.
  • Trap: reading inputs in the constructor, or starting timers with no cleanup.

Practice — level up

0/1 solved

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

ExplainA timer that cleans up

Greenhouse's PlantTimer shows how long ago a plant was watered and refreshes every minute using setInterval. It receives the plant as an input. Explain where you would start the timer, where you would stop it, and why neither belongs in the constructor or should be skipped.