Error: Template Update Required Due to Observable Value Change - Fixing the ExpressionChangedAfterItHasBeenCheckedError

After searching through numerous SO posts in search of a solution, I finally stumbled upon one that involved a hacky implementation. The issue at hand involves an observable extracted from the ngrx store which I then subscribe to:

this.navigationSelected$ = this.store.pipe(select(currentlySelectedNavigation));

this.navigationSelected$.subscribe(res => {
  ...
});

This subscription is used within the template with an ngIf statement that depends on the value of this observable:

<profile-navigation *ngIf="(navigationSelected$ | async) == navigationLayout[0].location"></profile-navigation>

However, each time the navigationSelected$ value changes, it triggers the following error:

ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'ngIf: [object Object]'. Current value: 'ngIf: false'.

Even though calling cdRef.detectChanges() at the end of the subscription resolves the issue, the error persists and the solution feels like a workaround. Is there a better approach to achieve the desired outcome?

Answer №1

To solve this problem, I typically include a debounceTime(0).

I like to use this line of code: this.selectedLink$ = this.dataStore.pipe(select(currentNavItem), debounceTime());

Answer №2

Each time the navigationSelected$ value changes, an error is triggered:

This error indicates that the value has changed twice.

Finding and fixing these errors on a selector can be challenging. It's not necessarily a problem with the view itself but rather with the store changing state before and after rendering the view. This often suggests that a dispatch should occur after a setTimeout() call.

The issue arises when another part of your code must change the state to prevent the view from causing errors. This dependency is less than ideal.

An alternative approach is to emit the value using EventEmitter.

<profile-navigation *ngIf="(navigationSelectedSafe$ | async) == navigationLayout[0].location"></profile-navigation>

public navigationSelectedSafe$ = new EventEmitter<any>(true); // must be true

this.navigationSelected$.subscribe(res => navigationSelectedSafe$.emit(res));

By using EventEmitter(true), values are emitted after a setTimeout(), preventing change errors in the view.

You can also explore your source code for instances where you use @Output() and try changing it to EventEmitter(true) to resolve the issue.

Typically, encountering this error on a selector indicates extensive state-related work outside of views. A component that needs to notify a change should utilize @Output(), but if it dispatches instead, it bypasses the view process, leading to such issues.

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

Maximizing Performance of JSON.stringify in Angular

In my Angular app, I have a service that retrieves JSON data from an API. At times, this API sends back over 400 records (JSON Objects). When I directly access the endpoint in my browser, it takes around 5 seconds to load all the JSON data onto the page. ...

What is the location of the file storage while executing ng serve?

After running ng serve, where exactly are the generated files stored? I am facing an issue where the app works fine with ng serve but encounters problems during production build. I should also add that I am using the webpack version of angular-cli. ...

Tips for disabling the download prompt in Chrome with the help of Protractor

Customize Chrome options for better performance: 'chromeOptions': { args: [ 'disable-extensions', 'safebrowsing-disable-extension-blacklist', 'safebrowsing-disable-download-protection', ...

Dealing with a Typescript challenge of iterating over a tuple array to extract particular values

I am struggling with writing a function that extracts names from an array of tuples, where each tuple includes a name and an age. My current attempt looks like this: type someTuple = [string, number] function names(namesAndAges: someTuple[]) { let allNa ...

Is the client component not initializing the fetch operation?

On my page, there is a sidebar that displays items by fetching data successfully. However, when I click on one of the sidebar items to pass props to another component for fetching data, it doesn't fetch any data until I manually click the refresh butt ...

Problem with Ionic2 star rating component

I am currently learning how to use rating stars in my Ionic2 app. I came across a helpful link on setting up rating stars in Ionic2. However, I encountered an issue when I tried to add the output tag. Can someone assist me with this problem? rating.html ...

The function type '() => JSX.Element' cannot be assigned to the type 'ReactNode'

I am encountering an issue while trying to display a component using an object. The code is throwing an error: const Login = () => <>login</> const publicRoutes = [ { path: '/login', component: Login } ] function AppR ...

Navbar Username in Next.js with Typescript and Supabase Integration

I'm currently facing an issue with retrieving the username of a user to display in my navbar. The desired username is stored in the "username" column of the table called "profiles" in my Supabase database. However, the data that's populating the ...

Creating an XML file with Angular 2: Step-by-step guide

While attempting to create XML files using Angular 2, I encountered an issue when trying to include tags with a namespace using xml-Writers. The error message displayed was: XML Parsing Error: Prefix not bound to a namespace' at the IR name space: ...

Tips on selecting specific text from a drop-down menu

After struggling to find a solution for retrieving the text of a selected item from a dropdown, I decided to create a common directive. This directive would allow me to easily access the text for all dropdown items when used in my code. Below is the snippe ...

Guide to utilizing services in Angular 2

As I've developed a service with numerous variables and functions, my goal is to inject this service into multiple components. Each component should have the ability to update certain variables within the service so that all variables are updated once ...

crafting connections in 3D using TypeORM (ORM)

I attempted to construct a database schema involving users, groups, documents, and permissions. Users can be part of multiple groups Groups can have multiple users Users can possess permissions for documents Groups can have permissions for documents Perm ...

Dealing with null exceptions in Angular 4: Best practices

Hi there, I am encountering an issue with binding my model data to HTML fields where when I try to edit the data it returns an error saying "cannot read value of null". How can I resolve this? Here is the HTML code snippet: <div class="form-group"> ...

Dealing with observable errors in Angular 2 beta.12 and RxJS 5 beta.3

Greetings, Currently, I am working with Angular2 beta 12 within VS2015. Upon updating from rxjs version 5.0.0-beta.2 to beta.3, I started encountering several exceptions primarily related to promises. For instance: The property map is not present in th ...

Swapping the content of the API response with Angular 11 in the HTML

When the output of row.remarks is 1, I want to display it as "passed" and when it's 0, I want it to be displayed as "fail" in the HTML while using mat-table. HTML <ng-container matColumnDef="remarks"> <th class="font& ...

Guide to adding a CSS class to an Ionic2 toast

i found a helpful resource on applying cssClass to my toast component. within my HTML, I have buttons: <button ion-button (click)="presentToast()"> toast</button> Here is the code snippet from my .ts file: presentToast() { let toast = t ...

In Typescript, try/catch blocks do not capture return values

I am currently working on a function that performs database operations, with the implementation contained within a try/catch block. Here is an example: async function update({id, ...changes}): Promise<IUserResult> { try { //insert code here retu ...

Unusual behavior exhibited by ng-if within a widget

Hey there, seeking some assistance here. I'm currently making edits to a widget and within the client HTML code, I've come across two ng-if statements (the first one was already there, I added the second). <li> <a ng-if="data.closed ...

Using the OR operator in Angular's *ngIf directive within a component's HTML

Need help with an *ngIf statement using OR in Angular, but the second condition is not working as expected. See below for the code: <div *ngIf="router.url != '/one' || router.url != '/two'"> show something </div> Any su ...

Optimizing media queries with Angular: A comprehensive guide

I am currently using NgZone to handle media queries in my Angular project. I am curious if there is a more efficient way to achieve this. import { NgZone } from '@angular/core'; const SMALL_WIDTH_BREAKPOINT = 840; export class AppComponent im ...