Encountering ExpressionChangedAfterItHasBeenCheckedError in Angular 17 even after invoking detectChanges method

I'm encountering a minor problem with Angular and its change detection mechanism. I have created a simple form where additional input fields can be added dynamically. However, every time I click the add button, an

ExpressionChangedAfterItHasBeenCheckedError
is thrown in the console. When I use a regular ngFor loop, the error appears in the console but the new input field is still displayed. On the other hand, when I utilize Angular's new @for directive, the error shows up in the console and the new input field does not appear on the screen. I have tried calling both detectChanges and markForCheck, but it did not resolve the issue.

public properties: Map<number, string> = new Map<number, string>();

public addProperty() {
  const id: number = this.properties.size ?
    Array.from(this.properties.keys()).reduce((a, b) => a > b ? a : b) + 1 : 1;

  this.properties.set(id, 'placeholder');
  this.changeDetectorRef.detectChanges();
}
<button class="btn btn-primary" (click)="addProperty()">+</button>

<div class="d-flex flex-column">
  <ng-container *ngFor="let attribute of properties.entries()">
    <span>{{ attribute[0] }}</span>
  </ng-container>
</div>

Any help to address this issue would be highly appreciated. Thank you in advance.

I have experimented with both ngFor and Angular's new @for, and found that the main difference is that the data added using @for is not displayed along with the console error. I also attempted manual change detection without success.

Answer №1

Angular's ngFor functionality is specifically tailored for arrays, which can sometimes cause confusion with change detection when dealing with references in maps. A simple solution is to convert the map into an array before passing it to ngFor, effectively resolving any potential change detection issues. Below is a functional example:

If you only need the keys or values, you can access them using properties.keys() or properties.values() respectively.

import { CommonModule } from '@angular/common';
import { ChangeDetectorRef, Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import 'zone.js';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule],
  template: `
    <button class="btn btn-primary" (click)="addProperty()">+</button>
    <div class="d-flex flex-column">
      {{properties.entries() | json}}
      <ng-container *ngFor="let attribute of mapEntriesToArray;trackBy: trackByFn ">
        <span>{{ attribute[0] }}</span>
      </ng-container>
    </div>
  `,
})
export class App {
  public properties: Map<number, string> = new Map<number, string>();

  constructor(private changeDetectorRef: ChangeDetectorRef) {}

  get mapEntriesToArray() {
    return Array.from(this.properties.entries());
  }

  public addProperty() {
    const id: number = this.properties.size
      ? Array.from(this.properties.keys()).reduce((a, b) => (a > b ? a : b)) + 1
      : 1;

    this.properties.set(id, 'placeholder');
  }

  trackByFn(index: number, item: any) {
    return index;
  }
}

bootstrapApplication(App);

Check out the live demo on stackblitz

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Observing changes in the DOM using Angular

Is there a way to programmatically track the changes of a DOM node? It can be time-consuming to detect the delta in the inspector, especially with angular components that have many class names. https://i.stack.imgur.com/ns6rR.png I am looking for a more ...

The [image link] in the NextJS image was loaded in advance using link preload, but it was not utilized within a short time after the window finished loading

While working on my blog website with NextJS, I encountered a warning in the console related to using next/image: The resource http://localhost:3000/_next/image... was preloaded using link preload but not used within a few seconds from the window's lo ...

Using Angular2 Pipes to display raw HTML content

I am currently working on developing a custom pipe in Angular2 that is capable of outputting raw HTML. My goal is to take input with newlines and convert them into HTML line breaks. Can anyone guide me on how to display raw HTML from an Angular2 pipe? Bel ...

Navigating the structure of an Angular project: sorting modules by core, features, and

Before we begin, let me clarify that this question is original and has not been asked before. I have thoroughly reviewed the angular guide on this topic. However, I still find myself with a handful of questions. Starting with feature modules - the concept ...

Unable to assign the selected attribute to a dynamically loaded Ion-select component in Ionic 2

I'm facing an issue with dynamically loading <ion-select> and setting default selection using the selected attribute. It doesn't seem to work as expected. Can anyone help me understand why? You can view the code on Plunker app/home.page.h ...

Ionic 6 prioritizes enhanced accessibility by implementing toast blocks that divert attention away from input fields

Scenario: My form is basic, but when the user tries to submit it with invalid inputs, I show a toast message with an error. Issue: Since upgrading to Ionic 6, I noticed that while the error toast is visible, I am unable to focus on any input fields until ...

Tips for testing an Angular service method that returns a JSON object

I have a service in Angular that processes JSON input and returns JSON output after some operations. My positive test case for this service is failing consistently. I suspect the reason for this failure might be: Expected Result : [ Object({ key: &apos ...

What types of modifications do ViewChildren and ContentChildren QueryLists keep an eye out for?

Imagine you come across the following lines of code: https://i.stack.imgur.com/7IFx1.png And then, in a different section, you stumble upon this code block: https://i.stack.imgur.com/qac0F.png Under what circumstances would () => {} be executed? Wha ...

Angular 4 has the capability to automatically log out in all tabs when a user logs out in one open tab

I am looking to implement a feature where I automatically log out from all open tabs when logging out from one tab. Currently, I am storing a jwt token in localStorage upon login and removing the token upon logout. Any suggestions on how I can utilize st ...

How to Toggle Visibility of Angular2 Material Drop Down Menu?

My Code <mat-form-field class="button-spacing"> <mat-select placeholder="select" [(ngModel)]="dropDownOne"> <mat-option *ngFor="let first of test1" [value]="first"> {{ first }} </mat-option> </mat-select> </mat-fo ...

A guide on automatically focusing on a Material UI Formik form TextField using React and TypeScript

I'm attempting to automatically focus my textField, but the 'autoFocus' attribute only seems to work after I submit the form and add a value. If no values are added (i.e. when opening the miui modal for the first time), the autoFocus does no ...

Utilizing EventEmitters for cascading operations in Angular 2 dropdown menus

I have a form with several cascading drop-downs - the selection in one drop-down determines the options available in the next. Each drop-down retrieves its values from an async data service, and Angular EventEmitter is used to handle events and populate su ...

Firebase data causing issues with ion-gesture recognition?

Hey there! I'm currently facing an issue with my ionic app. I added the ion-gesture to my project, but due to the ngFor loop pulling data from Firebase, the cards are unable to move. Here's a snippet of my code: <ion-card *ngFor="let po ...

Extracting the "defined" type from a TypeScript property during runtime

My current task Presently, I am iterating through the keys of an object and transferring their values to another object. interface From { [key: string]: string; } let from: From = { prop1: "foo", prop2: "23", }; interface To { [key: str ...

What method can be utilized to selectively specify the data type to be used in TypeScript?

Currently, I am facing a scenario where a certain value can potentially return either a string or an object. The structure of the interface is outlined as follows: interface RoutesType { projects: string | { all: string; favorite: string; cr ...

Guide on filtering FlatList Data in react native by selecting multiple categories from an array

User Interface Image I am looking to implement a filter functionality in the FlatList data based on top categories, where the filter button allows for multiple selections. The FlatList data is stored in the HotelData array, and the categories are also re ...

Install NPM without changing directories to the folder

Currently, I am using Windows Powershell and a pipeline to create the package for an application deployment. Here is the pipeline setup: https://i.stack.imgur.com/am2iR.png My current obstacle revolves around the "npm install" command, as I want to avoid ...

What is the process for generating flexible paths (URL strings) in angular applications?

Within my <app-parent> component, I have multiple buttons that each open a new floating panel on top of the parent. These floating panels also contain buttons that trigger the opening of additional floating panels, creating a stacking effect. My go ...

Challenges in handling asynchronous data within static JSON objects in Angular2

I have a service set up with some static objects that are being utilized in my UI. fetchRulesVariables() fetchRuleVariables() { let variables = [ { name: 'Credit Funding Type', id: 1, multiple: ...

The dynamically rendered component cannot be assigned to the type 'IntrinsicAttributes & ContentOutlineProps & ContentBrainstormProps'

I am facing an issue on my page where a <SideBar /> component is causing a Typescript error with the setActivePage hook. The error message points to a specific line in my code: const Content: (({ question_blocks, }: ContentBrainstormProps) => JSX. ...