How to Use ngDoCheck in Angular

The ngDoCheck lifecycle hook in Angular allows you to implement custom change detection logic for cases where Angular’s default change detection isn’t sufficient. As the creator of CoreUI with over 11 years of Angular development experience, I use ngDoCheck for components that need to detect changes in complex objects, arrays, or when working with immutable data structures. This hook runs on every change detection cycle, so it requires careful implementation to avoid performance issues.

Implement the DoCheck interface and ngDoCheck method to create custom change detection logic that runs on every change detection cycle.

import { Component, Input, DoCheck, KeyValueDiffer, KeyValueDiffers } from '@angular/core'

@Component({
  selector: 'app-object-tracker',
  template: `
    <div>
      <h3>Object Changes Detected:</h3>
      <ul>
        <li *ngFor="let change of detectedChanges">
          {{ change }}
        </li>
      </ul>
      <div>
        <strong>Current Object:</strong>
        <pre>{{ config | json }}</pre>
      </div>
    </div>
  `
})
export class ObjectTrackerComponent implements DoCheck {
  @Input() config: any = {}

  detectedChanges: string[] = []
  private differ: KeyValueDiffer<string, any>
  private previousValue: any

  constructor(private differs: KeyValueDiffers) {
    this.differ = this.differs.find({}).create()
  }

  ngDoCheck(): void {
    // Check for changes in the config object
    const changes = this.differ.diff(this.config)

    if (changes) {
      this.detectedChanges = []

      changes.forEachAddedItem(item => {
        this.detectedChanges.push(`Added: ${item.key} = ${item.currentValue}`)
      })

      changes.forEachChangedItem(item => {
        this.detectedChanges.push(`Changed: ${item.key} from ${item.previousValue} to ${item.currentValue}`)
      })

      changes.forEachRemovedItem(item => {
        this.detectedChanges.push(`Removed: ${item.key} (was ${item.previousValue})`)
      })
    }

    // Custom logic for deep object comparison
    if (this.hasDeepChanged(this.config, this.previousValue)) {
      console.log('Deep changes detected in configuration')
      this.onConfigurationChanged()
    }

    this.previousValue = JSON.parse(JSON.stringify(this.config))
  }

  private hasDeepChanged(current: any, previous: any): boolean {
    return JSON.stringify(current) !== JSON.stringify(previous)
  }

  private onConfigurationChanged(): void {
    // Perform actions when configuration changes
    console.log('Configuration has been updated')
  }
}

The ngDoCheck hook runs after every change detection cycle, making it powerful but potentially expensive. Use Angular’s Differs service for efficient object and array change detection instead of manual comparisons. Implement custom logic only when Angular’s default change detection misses changes in complex data structures. Be cautious about performance - avoid heavy computations or creating new objects in ngDoCheck as it runs frequently.

Best Practice Note:

In CoreUI components, we use ngDoCheck sparingly and only for components that manage complex configuration objects or work with immutable data patterns. We always combine it with OnPush change detection strategy to minimize performance impact while ensuring our enterprise components respond correctly to all data changes.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author

Subscribe to our newsletter
Get early information about new products, product updates and blog posts.

Answers by CoreUI Core Team