How does *ngIf affect the DOM and component lifecycle?

MediumIntermediateAngular
Preparing for interviews?

Use guided tracks for structured prep, then practice company-specific question sets when you want targeted interview coverage.

Quick Answer

*ngIf is a structural directive that conditionally creates and destroys an embedded view. That means DOM nodes, component instances, directives, listeners, and template bindings inside the *ngIf block are actually created when the condition becomes true and destroyed when it becomes false.

Answer

Overview

*ngIf does not “hide” elements. It adds/removes a chunk of template by creating/destroying an embedded view (EmbeddedViewRef) in a ViewContainerRef. When the view is removed, Angular destroys everything inside it (components, directives, pipes, listeners) and runs ngOnDestroy.

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
7 / 37