Interview answer drill

Use this Angular interview question to rehearse a quick answer, common mistake, follow-up, and production pitfall.

What’s the difference between constructor, ngOnInit, and ngAfterViewInit, and which one is correct for DOM/ViewChild access?Frontend interview answer

HighIntermediateAngular
Interview focus

This Angular interview question tests whether you can explain Angular constructor vs ngOnInit vs ngAfterViewInit: when to use, connect it to production trade-offs, and handle common follow-up questions.

  • Angular constructor vs ngOnInit vs ngAfterViewInit: when to use explanation without falling back to memorized docs wording
  • Lifecycle and Components reasoning, edge cases, and production failure modes
  • How you would answer the most likely Angular interview follow-up
Practice more Angular interview questions
Interview quick answer

constructor is for DI + trivial class setup, ngOnInit is for initialization that depends on inputs/bindings, and ngAfterViewInit is for work that needs the component view (DOM, ViewChild). The production follow-ups are what static ViewChild really changes, why static:true breaks under *ngIf/*ngFor, and when afterNextRender is a better post-render tool than guessing in the constructor.

Full interview answer

Core idea

These run at different moments in the component lifecycle. The right hook depends on what you need: DI only (constructor), inputs/bindings (ngOnInit), or the rendered view / ViewChild / DOM (ngAfterViewInit).

Hook

When it runs

What it’s for

DOM / ViewChild availability

constructor

When the class instance is created (before Angular initializes bindings).

Dependency injection + minimal field initialization (no Angular-dependent logic).

❌ Not safe for DOM. View is not created. ViewChild not resolved.

ngOnInit()

Once, after Angular sets data-bound inputs (after first ngOnChanges).

Initialization that depends on inputs, services, starting streams, fetching data.

⚠️ Usually not for DOM. ViewChild only if @ViewChild({ static: true }).

ngAfterViewInit()

Once, after Angular finishes creating the component’s view + child views.

Work that needs the rendered view: @ViewChild, DOM measurements, focus, 3rd-party widgets init.

✅ Safe for DOM/ViewChild (default static: false).

Constructor vs ngOnInit vs ngAfterViewInit

Which one is correct for DOM / ViewChild?

Use ngAfterViewInit() for DOM/ViewChild access in most cases. That’s when Angular guarantees the view exists and view queries (default static: false) are resolved.

Important nuance: @ViewChild static option

@ViewChild(..., { static: true }) resolves earlier (before/at init), so it can be used in ngOnInit() if the element is always present (not inside *ngIf/*ngFor). Default is static: false, which is available in ngAfterViewInit().

TYPESCRIPT
import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core';

@Component({
  selector: 'app-demo',
  template: `
    <input #nameInput />
    <!-- If this input were under *ngIf, static:true would be wrong -->
  `
})
export class DemoComponent implements OnInit, AfterViewInit {
  // Case A (common): default static:false => available in ngAfterViewInit
  @ViewChild('nameInput') nameInput?: ElementRef<HTMLInputElement>;

  // Case B: static:true => available in ngOnInit (ONLY if always present)
  // @ViewChild('nameInput', { static: true }) nameInput!: ElementRef<HTMLInputElement>;

  constructor(/* inject services here */) {
    // DI only. No DOM.
  }

  ngOnInit(): void {
    // Good: init that depends on @Input() or services.
    // If using static:true, you *can* access nameInput here.
  }

  ngAfterViewInit(): void {
    // Safe place for DOM/ViewChild
    this.nameInput?.nativeElement.focus();
  }
}
                  

Broken-before-fixed-after example

Static queries are not “faster DOM access.” They only work early when the queried node is guaranteed to be present in the initial template. If the element is behind *ngIf, static: true is the wrong fix and usually produces undefined in exactly the interview scenario where someone says “but I moved it to ngOnInit already.”

TYPESCRIPT
import { Component, ElementRef, ViewChild } from '@angular/core';

@Component({
  selector: 'app-broken-static-query',
  template: `
    <input *ngIf="showInput" #nameInput />
    <button type="button" (click)="showInput = true">Show</button>
  `
})
export class BrokenStaticQueryComponent {
  showInput = false;

  // ❌ Wrong: the node is not guaranteed to exist in the initial view tree.
  @ViewChild('nameInput', { static: true }) nameInput?: ElementRef<HTMLInputElement>;

  ngOnInit(): void {
    console.log(this.nameInput); // still undefined
  }

  // ✅ Fix: keep the default query and use ngAfterViewInit or a later render hook
  // after the input actually exists.
}
                  

Scenario

Correct hook

Why

Read @Input() values, set up streams, start API calls

ngOnInit

Inputs are set; component is initialized.

Access @ViewChild / measure DOM / focus element

ngAfterViewInit

View is created; queries are resolved.

ViewChild element is always present (not under *ngIf/*ngFor) and you need it early

ngOnInit + @ViewChild({ static: true })

Static query resolves before init.

Access projected content via @ContentChild

ngAfterContentInit

Projected content is initialized (different from the view).

Picking the right lifecycle hook

Common pitfall

If you change a bound value inside ngAfterViewInit, you can trigger ExpressionChangedAfterItHasBeenCheckedError in dev mode. Fix by avoiding sync bound mutations there, or scheduling them (microtask) / triggering a follow-up change detection deliberately (advanced).

Newer Angular nuance: afterNextRender

If the real requirement is “run this after Angular finishes rendering,” newer Angular also gives you render callbacks like afterNextRender. That helps with measurements, focus, or third-party widget setup after a render pass. It does not change the core decision: constructor is still for DI, ngOnInit is still for input-dependent init, and view-dependent work still belongs in a post-render phase.

Summary

constructor = DI + minimal setup. ngOnInit = initialization that depends on inputs/bindings. ngAfterViewInit = anything that needs the rendered view (DOM, ViewChild). For DOM/ViewChild access, ngAfterViewInit is the default correct choice, with the exception of @ViewChild({ static: true }) when the element is guaranteed to exist.

Similar questions
Guides
Preparing for interviews?

Use this as one explanation rep, then continue with the Angular interview questions cluster or a guided prep path.