Unable to update Angular view using the ChangeDetection.onPush strategy

I'm facing a challenge in updating the view of an Angular Component whenever there are changes in the data. I explored the ChangeDetectionStrategy.OnPush and hoped it would resolve the issue, but unfortunately, it didn't work out as expected.

The component in question is 'upcoming-studies', which is nested within the 'studies' component.

upcoming-studies.component.html

<div>
  <ngx-datatable
    #upcoming
    class="material"
    [headerHeight]="50"
    [footerHeight]="50"
    [rowHeight]="'auto'"
    [rows]="rows"
    [columns]="columns"
    [columnMode]="'flex'"
    [selected]="selected"
    [selectCheck]="selectUnselect"
    [selectionType]="'single'"
    [limit]="10"
    (select)='onSelect($event)'>
  </ngx-datatable>
</div>

The [rows]="rows" attribute fetches data from the backend using an HTTP call. The goal is to update the view whenever the 'rows' variable is updated or when an HTTP call is made.

upcoming-studies.component.ts

        @Component({
        selector: 'rmis-upcomingstudies',
        templateUrl: './upcoming-studies.component.html',
        changeDetection: ChangeDetectionStrategy.OnPush,
        styleUrls: ['./upcoming-studies.component.css']
    })
    export class UpcomingStudiesComponent implements OnInit, OnChanges {

        // ToDo: Check specific data types
        @Input() rows = [];
        @Input() temp = [];
     constructor(private studiesService: StudiesService,
                    private exceptionService: ExceptionService,
                    private cd: ChangeDetectorRef) {
            this.columns = [
                {prop: 'protocol_number', name: 'Protocol Number', flexGrow: 1},
                {prop: 'start_date', name: 'Start Date', flexGrow: 1},
                {prop: 'end_date', name: 'End Date', flexGrow: 1},
                {prop: 'patient_count', name: 'Patient Count', flexGrow: 1},
                {prop: 'trial_country', name: 'Country', flexGrow: 1},
            ];
        }

        ngOnInit() {
            this.getUpcomingStudies();
        }
        ngOnChanges() {
        //Need to implement logic for detecting changes in 'rows' and 'temp' variables 
}

Despite utilizing ChangeDetectionStrategy, the number of rows displayed on the UI does not change even after receiving updated data from an external HTTP call. Any suggestions on how to make this functionality work properly?

Update 1: It seems that the @Input() variables are not being updated, preventing proper change detection. Is there an alternative solution?

Update 2: Changes have been made in updating the 'rows' and 'temp' variables. The upcoming-studies component receives these values as inputs from the studies component, which retrieves them via an HTTP call.

studies.component.html

  <upcoming-studies [rows] = rows [temp] = temp>
    </upcoming-studies>

An HTTP call is made by the studies component to populate the 'rows' and 'temp' arrays with data.

studies.component.ts

public rows = [];
public temp = [];
ngOnInit() {
    this.getUpcomingStudies();
}
    getUpcomingStudies() {
    this.studiesService
        .getUpComingStudies()
        .subscribe(
            (data) => {
                this.temp = data['records'];
                this.rows = this.studiesService.util_to_cal_time(data['records']);
            },
            (err: HttpErrorResponse) => {
                this.exceptionService.errorResponse(err);
            },
            () => {
            }
        );
}

Initially, the 'getUpcomingStudies' method is called within the studies component's ngOnInit(). Subsequently, it can be triggered from another component. Further details can be provided if necessary.

util_to_cal_time - Utility function to modify time formats within the array.

util_to_cal_time(studies: Array<any>) {
        for (const each of studies) {
            const sDate = new Date(each.start_date * 1000);
            each.start_date = sDate.getUTCMonth() + 1 + '/' + sDate.getUTCDate() + '/' + sDate.getFullYear();
            const eDate = new Date(each.end_date * 1000);
            each.end_date = eDate.getUTCMonth() + 1 + '/' + eDate.getUTCDate() + '/' + eDate.getFullYear();
        }
        return studies;
    }

Answer №1

To resolve this issue, simply activate the modification detection within the array. After populating the "rows" and "columns" component variables, include the following code snippet:

this.rows = [...this.rows];
this.columns = [...this.columns];

Answer №2

After encountering this issue, I successfully resolved it without the need for ChangeDetection. In a previous post, I mentioned that the problem lied in how I was invoking a component method. I mistakenly used the "new" keyword to create a new instance of the component each time, preventing my old component from recognizing changes. This oversight led me to delve deeper into understanding ChangeDetectionStrategy. Thank you to everyone who contributed valuable insights!

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

I'm on the lookout for a component similar to angular-ui-tree that is compatible with angular

As a new developer, I am in search of a component similar to: But specifically for Angular 6, with all the same functionality (drag-and-drop capability, nested items, JSON structure, etc.). I have come across some components that either lack dragging fun ...

Why are my radio buttons being selected automatically? Is there a way to set just one as the default option in Angular 9?

I am currently facing an issue with two radio buttons. What I want is for the admin radio button to display one form when clicked, and the user radio button to display another form. Currently, both are checked by default and I am unsure why. I only want on ...

Extract information from a complex nested structure within an array

Can someone assist me with extracting only the username from the response provided below? I am able to access other data but struggling with this particular aspect. [ { "_id": "5f44d450aaa72313549d519f", "imageTitle": "u ...

What is the most efficient method for monitoring if data has been fully loaded in a reactive manner?

Consider the code snippet below: heroes: Obserable<Hero[]>; private _loadHeroes: EventEmitter<void> = new EventEmmiter; constructor(heroService: HeroService) { this.heroes = _loadHeroes.switchMap(() => heroService.fetchHeroes()); } ...

What is the best way to return Promise<void> or Promise<any> as a return type?

If I want to return a promise in TypeScript that can be either of type Promise<void> or Promise<any>, how can I achieve this? I have attempted: Promise<void | any> Promise<void> | Promise<any> However, the following error o ...

Issue TS2322: The compiler has detected a mismatch in types, where a number is being assigned to a string, which is not compatible

I'm currently working on an app where I need to retrieve posts by user before displaying a specific post based on its id when clicked. However, I encountered the following errors: ERROR in src/app/cars/car-detail/car-detail.component.ts(25,11): err ...

From milliseconds to hours: a straightforward conversion

Given a start date, time and end date, time, I am trying to calculate the total travel duration. The output is in milliseconds and needs to be converted into hours format. Despite attempting some solutions shared here, I haven't been successful. < ...

After installing Angular Material, receiving an error stating "Module '@angular/platform-browser/animations' not found."

Every time I launch my application, an error pops up: The module '@angular/platform-browser/animations' cannot be found. Here is the content of my package.json file: { "name": "oscar-app-ihm", "version": " ...

What does the reportProgress function do in HTTP services with JavaScript?

Can someone explain the functionality of reportProgress in JavaScript, specifically when used with Angular Typescript? I am having trouble finding documentation on this. return this.httpClient.request<ProductResponse>('get',`${this.basePath ...

The combination of TypeScript 2.6 and material-ui 1.0.0-beta.24's withStyles with react-router withRouter is resulting in the error message: "Property 'classes' is missing in type."

Using the high order components withStyles and withRouter together has been a smooth process so far. However, after upgrading to the latest versions of these components, an error occurred. Learn more about higher-order components List of packages used: ...

What is the solution for this problem in TypeScript involving an API service call?

Trying to utilize the API Service to fetch data and display the response as an object created by a class constructor Currently executing a Typescript code that interacts with the API Service import * as request from "request"; import { Users } from "./Us ...

Angular Checkbox Plugin

I'm currently working with Angular and I seem to be facing an issue that may be related to it. I have a checkbox that functions properly when clicked, but the problem arises when I select another item. It seems like the checkbox retains its previous ...

Is there a way to seamlessly transfer (optional) parameters from a CloudFormation template to a CDK resource within a CfnInclude without statically defining the list of parameters?

Trying to grasp these syntax rules, unsure if it's possible. We have numerous CloudFormation templates that we want to deploy using CDK by constructing them with CfnInclude. The issue is that CfnInclude always needs an explicit parameters argument if ...

Building an AngularJS Service with TypeScript that is Non-Singleton: A Step-by-Step Guide

I need help converting an AngularJS Typescript Service into a Non-Singleton. Can anyone provide guidance on how to achieve this? (Note: This is not the same as other questions that focus on achieving this in JS) I have included some simple pseudo code be ...

Testing Angular 7 Services with RxJs6: Verifying Error Handling with throwError

I am interested in testing the throwError functionality. When I test with a wrong id of 0 using getById, my expectation is that throwError should return an error. This is my service: getById(fooId): Observable<Foo> { return this.getAll().pipe(mer ...

Utilizing process.env in TypeScript can be a bit tricky as dot notation is not effective for accessing its properties

When I set my scripts to: "start": "NODE_ENV=development nodemon dist/Server.js", I am encountering an issue when trying to access NODE_ENV in my code. Both dot and bracket notation return undefined: The dependencies in my project are: "@types/node": "^8. ...

Angular 7 with Webpack: Unresolved Error - Unable to resolve parameters for e

After diving into the world of Angular + Webpack last week, I encountered a roadblock while trying to set it up with Django as my backend. Despite following multiple guides, I'm struggling to even launch a basic Hello World example. The Google Chrome ...

Is it possible to perform a comprehensive text search in Mongoose using multiple criteria and connecting them with an AND operator?

Currently, I am able to smoothly perform a full text search using just one word. However, I'm facing difficulty in searching for multiple parameters or entering them at the same time. This is how my function looks like: export const searching = ( ...

Updating data within rows in Angular 4

Is there a way for me to update the value in my row based on a selected ingredient from a dropdown list? I want the unit price to be patched into the input field when a specific ingredient is chosen. You can find the relevant code snippets by visiting TH ...

Best practices for working with child components in Vue.js using TypeScript: Steer clear of directly mutating props

I feel like I'm stuck in a loop here. Currently, I have a Vue.js 2 app set up and running with TypeScript. However, I'm encountering an issue when trying to pass data to a child component that originates from the store. <template> < ...