“Expression has changed after it was checked” – error in Angular

The “Expression has changed after it was checked” error in Angular indicates that a component property was updated during Angular’s change detection cycle, causing a mismatch between the DOM and the component’s data. To fix this, you can delay the update by using setTimeoutPromise.then, or an asynchronous observable, or update the property in a lifecycle hook before the DOM update. 

Here’s a more detailed explanation and common solutions:

Understanding the Error
  • Angular’s change detection mechanism checks for changes in component properties and updates the DOM accordingly. 
  • The error occurs when a change is made to a component property during this detection cycle, before the DOM has a chance to reflect the change. 
  • This can happen with asynchronous operations like HTTP requests, timers, or event listeners that update data within the change detection cycle. 
Solutions
  1. Delay the Update with setTimeoutPromise.then, or Asynchronous Observable:
    • Wrap the code that modifies the component property in a setTimeoutPromise.then, or an asynchronous observable (like RxJS).
    • This forces the update to happen after the current change detection cycle is complete, preventing the error. 
TypeScript
    setTimeout(() => {      this.myProperty = newValue;    }, 0);
TypeScript
    Promise.resolve().then(() => {      this.myProperty = newValue;    });
TypeScript
    fromEvent(document, 'click').subscribe(() => {      this.myProperty = newValue;    });
  1. 1. Update the Property in a Lifecycle Hook:
    • Move the code that modifies the component property to a lifecycle hook like ngOnInitngAfterContentInit, or ngAfterViewInit. 
    • These hooks are called after Angular has completed its initial change detection and DOM updates, so the change is less likely to interfere with the cycle. 
  2. 2. Manually Trigger Change Detection (Use with Caution):
    • Inject ChangeDetectorRef into your component and use detectChanges() to manually trigger change detection. 
    • This can be useful in specific scenarios, but it’s generally best to avoid manually triggering change detection and use asynchronous solutions or lifecycle hooks whenever possible. 
  3. 3. Refactor your code:
    • Identify the component, the binding, and the expression that are causing the issue. 
    • Determine which property is changing the expression’s result between the regular detectChanges and the checkNoChanges checks. 
    • Refactor your code to prevent changes to the property during the change detection cycle. 
    • For example, move the update to a lifecycle hook or use asynchronous operations. 
Debugging
  • The error message and stack trace can help you pinpoint the exact location where the change is happening.
  • Use the Chrome DevTools debugger to set breakpoints and inspect the values of variables during the change detection cycle.
  • Angular University has a blog post on debugging “Expression Changed” errors that can be helpful. 
Important Considerations
  • Avoid updating component properties directly within template expressions or event handlers. 
  • Use the correct lifecycle hooks for your use case to ensure that updates occur at the appropriate time. 
  • If you need to update the DOM or perform other actions that might interfere with change detection, consider using asynchronous operations or manually triggering change detection. 

Angular Testing Library | Testing Library

The problem

You want to write maintainable tests for your Angular components. As a part of this goal, you want your tests to avoid including implementation details of your components and rather focus on making your tests give you the confidence for which they are intended. As part of this, you want your testbase to be maintainable in the long run so refactors of your components (changes to implementation but not functionality) don’t break your tests and slow you and your team down.

This solution

The Angular Testing Library is a very lightweight solution for testing Angular components. It provides light utility functions on top of DOM Testing Library in a way that encourages better testing practices. Its primary guiding principle is:

The more your tests resemble the way your software is used, the more confidence they can give you.

So rather than dealing with instances of rendered Angular components, your tests will work with actual DOM nodes. The utilities this library provides facilitate querying the DOM in the same way the user would. Finding form elements by their label text (just like a user would), finding links and buttons from their text (like a user would). It also exposes a recommended way to find elements by a data-testid as an “escape hatch” for elements where the text content and label do not make sense or is not practical.

This library encourages your applications to be more accessible and allows you to get your tests closer to using your components the way a user will, which allows your tests to give you more confidence that your application will work when a real user uses it.

Source: Angular Testing Library | Testing Library

Angular profiler for performance tuning | Angular Newsletter

When facing a performance issue, the Profiler is perfect for identifying the problem’s root cause. For instance, it could highlight that one component is much slower than the others and gets refreshed for no good reason, indicating that a different change detection strategy is needed.

Source: Angular profiler for performance tuning | Angular Newsletter

Angular automated migration from ngIf and ngFor directives markup to control blocks

Directives such as *ngIf and *ngFor will soon get deprecated to favor the new control flow blocks.

E.g. old directives:

<ng-container *ngIf="isLoggedIn">...</ng-container>

Can now be replaced with the new syntax:

@if (isLoggedIn) {
   ...
}

An automated migration CLI command is available

5 tips on using Angular FormControl

We often learn Angular presented with two options for working with forms: Template driven or reactive (or both!)

In several cases, small forms (for instance, a login screen, a single text input, or a single dropdown) don’t need that kind of verbosity.

In this post, we will look at five straightforward yet valuable features of the FormControl object used on its own without bringing any additional config to the table.

Source: 5 tips on using Angular FormControl | by Alain Chautard | Angular Training

How to run Angular component tests (karma) for a certain folder or specific spec file

This runs all spec files that are descendants of the “my-area” folder and in the “Edge” browser.

ng test --include "src/app/my-area/**/*.spec.ts" --browsers=Edge

run a single spec file:

ng test --include "src/app/myarea/**/mytest.component.spec.ts" --browsers=Edge

Angular v19 will make components as standalone default

Angular v19 will make standalone: true the default for components, directives, and pipes.In v14 we introduced a developer preview “standalone” feature, which made it possible for the first time to build an application that didn’t rely on NgModules. Since then, standalone has been stabilized, and has become the recommended way to write Angular code by the Angular team. The CLI generates components with standalone: true by default, and the Angular docs teach standalone first to all new Angular developers. A

Source: The future is standalone!. Angular v19 will make standalone: true… | by Alex Rickabaugh | Sep, 2024 | Angular Blog