How does *ngIf affect the DOM and component lifecycle?

HighIntermediateAngular
Quick Answer

*ngIf is not a visibility toggle; it creates and destroys embedded views. The practical angle is lifecycle and debug behavior: state resets, ngOnDestroy cleanup, and the production choice between real teardown and simply hiding UI.

Answer

Debug mental model

*ngIf does not hide a subtree; it creates and destroys an embedded view. In production, that difference shows up as reset form state, fresh child instances, repeated init work, and cleanup bugs when subscriptions or listeners are tied to that subtree.

HTML
<!-- Shorthand -->
<app-child *ngIf="show"></app-child>

<!-- Roughly equivalent to -->
<ng-template [ngIf]="show">
  <app-child></app-child>
</ng-template>
                  

When condition flips

DOM result

Instance result

Lifecycle impact

false → true

Nodes are inserted into the DOM

New component/directive instances are created

constructor → (ngOnChanges) → ngOnInit → view/content hooks

true → false

Nodes are removed from the DOM

Instances are destroyed

ngOnDestroy runs; subscriptions/cleanup should happen here

true → true (condition stays true)

DOM stays

Same instances stay

Normal change detection updates bindings

What *ngIf actually changes
TYPESCRIPT
// child.component.ts
import { Component, OnDestroy, OnInit } from '@angular/core';

@Component({
  selector: 'app-child',
  template: `Child is alive`
})
export class ChildComponent implements OnInit, OnDestroy {
  constructor() {
    console.log('child: constructor');
  }

  ngOnInit(): void {
    console.log('child: ngOnInit');
  }

  ngOnDestroy(): void {
    console.log('child: ngOnDestroy');
  }
}

// parent template
// <button (click)="show = !show">toggle</button>
// <app-child *ngIf="show"></app-child>
                  

Topic

*ngIf behavior

Practical consequence

Component state

Reset on every re-create

Local fields, form state, and child component state are lost on hide/show

Subscriptions/listeners

Destroyed view stops emitting into template

If you subscribe manually, you must unsubscribe in ngOnDestroy (or use async pipe / takeUntilDestroyed)

DI scope

Component-level providers are torn down with the view

A service provided in the component gets a fresh instance on next show

View queries

ViewChild/ContentChild inside the block disappear

References become undefined when view is destroyed; guard access

Change detection cost

Removed subtree is not checked

Hiding heavy UI with *ngIf can reduce CD + DOM updates

Key implications interviewers care about

Technique

Does it remove from DOM?

Does it destroy component instances?

When to prefer

*ngIf

Yes

Yes

When you want real teardown (free resources, remove listeners, skip CD)

[hidden] / CSS (display:none)

No

No

When you need to preserve state and avoid re-creation cost

ng-container + else template

Same as *ngIf

Same as *ngIf

When you want clean conditional branching without extra wrapper DOM

*ngIf vs hiding

Common gotcha

What happens

Fix

Toggling a form with *ngIf

User input resets on every hide/show

Use [hidden] if you must preserve state, or persist the form model outside the child

Expensive init in ngOnInit

Runs every time the view is recreated

Cache in a service/facade, or keep component alive and just hide it

Memory leaks

Manual subscriptions keep running if not cleaned up

Use async pipe, takeUntilDestroyed(), or ngOnDestroy cleanup

Practical pitfalls
Summary

*ngIf creates/destroys an embedded view. True = build DOM + instantiate components/directives and run init hooks. False = remove DOM + destroy instances and run ngOnDestroy. Use it when you want real teardown and to skip change detection for that subtree; use hiding when you need to keep state alive.

Similar questions
Guides
Preparing for interviews?

Use the relevant interview-question hub first, then move into a concrete study plan before targeted company sets.