ngAfterViewChecked()

ngAfterViewChecked() in Angular

๐Ÿ” ngAfterViewChecked() in Angular: What It Is, When to Use It, and What to Avoid

Posted: June 3, 2025

✅ Introduction

ngAfterViewChecked() is one of Angular's lifecycle hooks. It’s invoked after every change detection cycle that affects the component’s view or its child views. This makes it a powerful—but potentially risky—place to run post-render logic. In this article, we'll explore what it does, when and how to use it, and key pitfalls to avoid.

⏱️ When Is ngAfterViewChecked() Called?

  • After ngAfterViewInit() (i.e., once the component's view has been initialized)
  • After every subsequent change detection cycle affecting the component’s view or its children

This means it runs many times, even when nothing has visibly changed.

๐Ÿ’ก When Should You Use It?

  • The DOM might change dynamically, and you need to measure or react to it
  • You want to run animations or layout logic after rendering
  • You need to interact with child components or view elements after updates

⚠️ Performance & Caution

Because this hook runs frequently, there are important constraints:

❌ Avoid:
  • Expensive calculations or DOM operations
  • Updating data-bound properties directly (can cause infinite loops)
✅ Use:
  • ChangeDetectorRef.detectChanges() with caution
  • setTimeout() or other async strategies to defer updates safely
⚠️ Warning: Avoid updating component state directly inside ngAfterViewChecked() — this can cause infinite change detection loops.

๐Ÿงช Examples

๐Ÿ“ Example 1: DOM Dimension Check

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

@Component({
  selector: 'app-after-view-checked-example',
  template: `<div #myDiv>{{ message }}</div>`
})
export class AfterViewCheckedExampleComponent implements AfterViewChecked {
  message = 'Initial message';

  @ViewChild('myDiv') myDivRef!: ElementRef;

  ngAfterViewChecked(): void {
    console.log('ngAfterViewChecked() called');

    if (this.myDivRef.nativeElement.offsetHeight > 50) {
      this.message = 'Div is now taller than 50px!';
    }
  }
}
  
๐Ÿ”„ Tip: This example may trigger change detection recursively. Use setTimeout() or async logic to avoid this.

๐Ÿ“ Example 2: Watching for Dynamic Height Changes

@Component({
  selector: 'app-dimension-checker',
  template: `<div #resizable>This content can resize.</div>`
})
export class DimensionCheckerComponent implements AfterViewChecked {
  @ViewChild('resizable') resizableDiv!: ElementRef;
  previousHeight: number | null = null;

  ngAfterViewChecked(): void {
    const currentHeight = this.resizableDiv.nativeElement.offsetHeight;

    if (this.previousHeight !== null && currentHeight !== this.previousHeight) {
      console.log('Div height changed to:', currentHeight);
    }

    this.previousHeight = currentHeight;
  }
}
  
๐Ÿ“Œ Use this pattern to track layout changes passively without triggering state updates that cause loops.

๐Ÿ‘ถ Example 3: Interacting with Child Component State

import { Component, AfterViewChecked, ViewChild } from '@angular/core';
import { ChildComponent } from './child.component';

@Component({
  selector: 'app-parent',
  template: `<app-child></app-child>`
})
export class ParentComponent implements AfterViewChecked {
  @ViewChild(ChildComponent) childComp!: ChildComponent;

  ngAfterViewChecked(): void {
    if (this.childComp?.someState) {
      console.log('Child component state updated:', this.childComp.someState);
    }
  }
}
  
๐Ÿ‘€ This can be useful when you need to observe internal state changes of child components after rendering.

๐Ÿšซ Common Pitfalls

❌ Direct State Mutation:
ngAfterViewChecked(): void {
  // BAD: This will cause a continuous loop
  this.someProperty = 'new value';
}
  
✅ Safe Update with Async:
ngAfterViewChecked(): void {
  setTimeout(() => {
    // GOOD: Update happens after current detection cycle
    this.someProperty = 'new value';
  });
}
  

๐Ÿง  Best Practices

  • ✅ Use ngAfterViewChecked() sparingly
  • ✅ Always wrap DOM interactions or view checks in conditions
  • ✅ Use setTimeout() or ChangeDetectorRef carefully
  • ❌ Never mutate bindings or state directly inside this hook
  • ✅ Prefer ngAfterViewInit() or ngAfterContentChecked() if possible

๐Ÿงพ Conclusion

ngAfterViewChecked() is a valuable lifecycle hook for detecting post-render changes, interacting with dynamic layouts, and accessing child component state after the view has been updated. But it comes with sharp edges:

  • It runs often
  • It can easily cause performance bottlenecks or infinite loops

Use it wisely—keep logic lightweight, avoid synchronous state changes, and lean on async strategies when needed.

Comments

Popular posts from this blog

Debouncing & Throttling in RxJS: Optimizing API Calls and User Interactions

Promises in Angular

Comprehensive Guide to C# and .NET Core OOP Concepts and Language Features