What Causes NG0100: Expression Has Changed After It Was Checked?

This error occurs when Angular's change detection detects a mismatch between the initial and final values of a binding or expression during the same change detection cycle. Common causes include:

  • Updating component properties inside ngOnInit or ngAfterViewInit.
  • Changing values inside asynchronous callbacks.
  • Direct DOM manipulations that bypass Angular's change detection system.
  • Improper use of third-party libraries that manipulate the DOM.

Common Scenarios and Solutions

1. Updating Properties in ngOnInit or ngAfterViewInit

Modifying component bindings after the first change detection cycle:

// Incorrect
ngOnInit() {
    this.title = 'Initial Value';
    this.title = 'Updated Value'; // NG0100 error
}

Solution: Use setTimeout to defer the change to the next cycle:

// Correct
ngOnInit() {
    setTimeout(() => {
        this.title = 'Updated Value';
    });
}

2. Changes in Asynchronous Callbacks

Updating properties inside an asynchronous operation:

// Incorrect
ngOnInit() {
    this.http.get('/api/data').subscribe(data => {
        this.property = data.value; // NG0100 error
    });
}

Solution: Use Angular's ChangeDetectorRef to manually trigger change detection:

// Correct
constructor(private cd: ChangeDetectorRef) {}

ngOnInit() {
    this.http.get('/api/data').subscribe(data => {
        this.property = data.value;
        this.cd.detectChanges();
    });
}

3. Direct DOM Manipulations

Manipulating the DOM directly without Angular's awareness:

// Incorrect
ngAfterViewInit() {
    document.getElementById('element').innerText = 'New Value'; // NG0100 error
}

Solution: Use Angular's Renderer2 for DOM manipulations:

// Correct
constructor(private renderer: Renderer2) {}

ngAfterViewInit() {
    const element = this.renderer.selectRootElement('#element');
    this.renderer.setProperty(element, 'innerText', 'New Value');
}

4. Third-Party Library Side Effects

Using third-party libraries that alter DOM or application state outside Angular:

// Incorrect
ngOnInit() {
    externalLibrary.init({
        callback: () => {
            this.value = 'New Value'; // NG0100 error
        }
    });
}

Solution: Wrap changes in Angular's NgZone:

// Correct
constructor(private ngZone: NgZone) {}

ngOnInit() {
    externalLibrary.init({
        callback: () => {
            this.ngZone.run(() => {
                this.value = 'New Value';
            });
        }
    });
}

Debugging NG0100

  • Analyze Error Messages: Angular's error message indicates the specific binding or property causing the issue.
  • Enable Debug Mode: Run Angular in development mode to log detailed error messages.
  • Inspect Lifecycle Hooks: Check where the property updates occur and ensure they align with Angular's lifecycle.
  • Use Breakpoints: Add breakpoints in the code to track the changes in property values.

Best Practices to Avoid NG0100

  • Defer property updates to the next change detection cycle using setTimeout or Promise.resolve.
  • Use ChangeDetectorRef to manually control change detection when necessary.
  • Prefer Angular's built-in methods like Renderer2 for DOM manipulations.
  • Wrap third-party library interactions in Angular's NgZone.
  • Write unit tests to ensure component bindings remain consistent during development.

Conclusion

The NG0100: Expression has changed after it was checked error is a common issue in Angular, but understanding its causes and following best practices can help developers prevent and resolve it effectively. By leveraging Angular's tools and lifecycle hooks, you can ensure your application runs smoothly and efficiently.

FAQs

1. What is NG0100 in Angular?

This error occurs when a property or expression changes after Angular's change detection cycle has completed.

2. How do I fix the NG0100 error?

Defer property updates using setTimeout or Promise.resolve, or use Angular's ChangeDetectorRef.

3. Can asynchronous operations cause NG0100?

Yes, updates in asynchronous callbacks can trigger this error if they modify bindings after the change detection cycle.

4. How do I debug NG0100 errors?

Analyze Angular's error messages, inspect lifecycle hooks, and use breakpoints to identify where property changes occur.

5. How can I prevent this error in Angular projects?

Follow Angular's lifecycle rules, use built-in tools like Renderer2 for DOM manipulations, and wrap third-party interactions in NgZone.