Angular not reflecting changes in array or boolean state

I am using a simple ngFor loop to display a list:

<a class="list-group-item " *ngFor="let user of chatsLists" (click)="viewChat(user)">
    <div class="media chat-list-text py-1" [ngClass]="{'align-items-center': !user.isActiveChat}">
        <span class="avatar avatar-md mr-2">
            <img [src]="user.userid.userImage" alt="Avatar">
        </span>
        <div class="media-body">
            <h6 class="list-group-item-heading mb-1">{{user.userid.userName}}
            </h6>

        </div>
    </div>
</a>

The data is being retrieved from an API function:

  chatsLists: any; //also tried with chatsLists = [];


  getChats() {
    this.api.getAllChats().subscribe((res: any) => {
      if (res.success) {
        this.chatsLists = res.data;
        this.chatdetails = this.chatsLists[0].messages;
        this.showChats = true;
      }
    })
  }

The ngFor loop is not updating when I change the boolean value in the function and it's not reflecting in the HTML file. I have also tried placing a simple conditional statement in the HTML:

<p *ngIf="showChats">Show </p>

Below is the full code of the component.ts file for reference:

this.showChats = true;

// Component code goes here

Answer №1

Utilizing ChangeDetectionStrategy.OnPush
involves ensuring that when making asynchronous calls outside of a component, you must explicitly instruct the component to update. Is this the approach you wish to take? If so, make sure to include changeDetectorRef in your constructor and use it to indicate when the component is ready for change detection:

constructor(..., private changeDetectorRef: ChangeDetectorRef) {

Furthermore, within your getChats function:

getChats() {
  this.api.getAllChats().subscribe((res: any) => {
    if (res.success) {
      this.chatsLists = res.data;
      this.chatdetails = this.chatsLists[0].messages;
      this.showChats = true;
      this.changeDetectorRef.markForCheck(); //Include this line here
    }
  })
}

Answer №2

One possible reason for this issue could be the implementation of the OnPush strategy. It is likely that the change detection has already occurred due to the asynchronous nature of the HTTP request and callback handling.

A recommendation would be to modify your subscription approach by utilizing the async pipe.

Here's an example:


  setChats() {
    this.chats$ = this.api.getAllChats().pipe(
      filter((res: any) => res.success),
      tap((res) => {
        this.chatsLists = res.data;
        this.chatdetails = this.chatsLists[0].messages;
        this.showChats = true;
      })
    );
    

Consider implementing something similar to the above code snippet and using {{ chats$ | async }} in your HTML template.

The provided code snippet could benefit greatly from variable typing and improved stream composition. When working with OnPush, it is highly recommended to stick with the async pipe for optimal performance.

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

The property 'setParentKeyForNodeData' is not found in the 'Model' type. Perhaps you meant to use 'setCategoryForNodeData'?

As I work with gojs and utilize an organizational chart, I have encountered a problem with one of the context menus. Specifically, when selecting "Remove Role", I receive an error message stating Property 'setParentKeyForNodeData' does not exist ...

Awaiting the outcome of the Typescript map function is non-existent

In order to find the subcategories of an article, I am utilizing a many-to-many relationship with TypeOrm that requires Ids. However, I encountered an issue where the map function is not properly waiting to push the results into the array. Below is the c ...

Using EventEmitter for Component Communication in Angular 2

I have a duo of components: AppComp and SimulationComp AppComp consists of a single function : createEmptyPromise() { return Promise.resolved('') } and it showcases the following html structure : <simulation-comp (simu)='createEm ...

Get a PNG file in the form of binary/octet-stream for download

https://i.sstatic.net/VFMbl.pngsteps to recreate the issue: I have a Blob object that I am saving as form data through a service. The response I receive has a content-type of application/octet-stream, as shown in the attached image. What result is expect ...

What could be causing the recurring error when attempting to push data into an array in Angular 10?

Trying to implement Angular Material Chips similar to the example on the site, but encountering an error indicating that the array is null. https://i.sstatic.net/1jBnF.png Component code snippet: import { Component, Input, OnInit } from '@angular/co ...

Get rid of Firebase hosting

Using angular2-cli and angularfire2, I attempted to integrate Github authentication but needed to add a callback URL. However, upon trying to log in via Github, I received an error stating my page had not been deployed. To address this issue, I executed t ...

Is it necessary to create a wrapper for Angular Material2 components?

I have multiple angular 5 projects in progress and my team is considering incorporating material design components from https://material.angular.io/. Would it be beneficial to create a wrapper layer to contain the material design components? This would me ...

Instructions for activating the "Navigate to Declaration" feature in TypeScript for JSON files using i18next

Currently, I am actively engaged in a project that involves the use of i18next with react and typescript. In this project, translation keys are defined within .json files. However, a notable drawback of transitioning to json for the translation files is l ...

Categorize array elements based on nested object property and combine them

My data structure includes an array as shown below: BasketDish [ { id: string; quantity: number; Dish: AsyncItem<Dish | undefined>; basketID: string; createdAt?: string | null; updatedAt?: string | null; basketDishDishI ...

The page does not appear to be updating after the onClick event when using the useState hook

Having difficulty re-rendering the page after updating state using the useState hook. Although the state value changes, the page does not refresh. export function changeLanguage(props: Props) { const [languageChange, setLanguageChange] = React.useState( ...

Is there a method in RXJS that allows an operator to pause and wait for a subscription to finish before proceeding with the workflow?

Being new to the world of RXJS, I have spent a considerable amount of time researching and seeking solutions on stackoverflow and various documentation sources before turning to ask for help here. However, despite my efforts, I am struggling to make my log ...

Show a select element with choices that change depending on another select element

I am currently working on a select dropdown component that utilizes the @Input option variable. My goal is to have another instance of this component display options based on the selection made in the first instance. Any suggestions on how to make this h ...

How can Observables be designed to exhibit both synchronous and asynchronous behavior?

From: Understanding the Contrasts Between Promises and Observables In contrast, a Promise consistently operates asynchronously, while an Observable can function in synchronous or asynchronous manners. This presents the opportunity to manipulate code in ...

The error message related to TupleUnion in TypeScript is indicating that the depth of type instantiation may be too deep and could

Recently, I've been delving into a TypeScript utility type known as TupleUnion. This useful type came to my attention through a fascinating Twitter post, and I've observed it being utilized in various Stack Overflow solutions. Here's how the ...

Merge the inverse property and inverse class selector with the current selector for enhanced specificity

I was looking at this jQuery code snippet: $("#Filter ul input:checked").each(function () { if (!$(this).prop("disabled") && !$(this).hasClass("ignoreInput")) { Is there a way to simplify this into just one selector? It seems like I'm ha ...

Typescript React Union type

I have developed a Card component with two different variants: Wrapper and Dashboard. Each variant comes with its own set of props. export type DashboardProps = { variant: CardVariant.Dashboard, primaryText: string, secondaryText: string, icon: Ove ...

After changing routes in Angular 4, the application experiences decreased speed and a continual increase in the number of nodes, particularly noticeable in Chrome but not in Firefox

After switching routes multiple times, I noticed a decrease in the app's speed. Upon inspecting the 'performance + memory' section using Chrome debugger, I observed an increasing number of DOM nodes. It seems that the DOM nodes are not prop ...

best practices for creating space between flexbox items

My task involves presenting a continuous scroll list of scheduled jobs using Angular Material. Each item in the list needs to be divided into three columns utilizing flexbox. Despite my efforts, I am struggling with adding space between the columns within ...

Calculate the total value of an object using Typescript

Here is the data that I have: [Products, Products, Products, Products] 0: Products {product_id: "1", Product_type_id: "11", Subtotal:450, …} 1: Products {product_id: "2", Product_type_id: "22", Subtotal:550, …} 2: Products {product_id: ...

Tips for combining values with Reactive Forms

Is there a way to merge two values into a single label using Reactive Forms without utilizing ngModel binding? <label id="identificationCode" name="identificationCode" formControlName="lb ...