When utilizing the OnPush strategy, the view of the child component does not undergo re-rendering

@Component({
    selector: "parent",
    template: `<child [userId]="(userID$ | async)"></child>`,
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class ParentComponent implements OnInit {
    userID$: BehaviorSubject<string> = new BehaviorSubject<string>(null);

    constructor(private router: Router) { }
    
    ngOnInit() {
        this.router.queryParams.subscribe(params => {
            //notify child component with new user ID
            this.userID$.next(params["id"])
        });
    }
}

@Component({
    selector: "child",
    template: `<div *ngIf="(userState$ | async) && userId">
                    {{(userState$ | async).user.id)}}
               </div>`,
    changeDetection: ChangeDetectionStrategy.Default
})
export class ChildComponent implements OnChanges {
    @Input() userId: string;
    private userState$: Observable<User>;

    constructor(private store: Store<store.AppState>) { }
    
    ngOnChanges(changes: SimpleChanges) { 
        //update the userState based on the userId received
        this.userState$ = this.store
                .select(state => state.user-list)                 
                .map(userList => userList[this.userId])
                .filter(user => !!user);
    }
}

The Child component receives the user ID from the Parent and finds the corresponding user in the ngrx store (userList), but the view of the Child component is not being re-rendered. Everything works well when the ChangeDetectionStrategy for the Child component is set to default. What could be causing this issue? Using Angular version 2.4

Answer №1

In order to update the model inside ngOnChanges(), you must explicitly trigger change detection.

export class ChildCmp implements OnChanges {
    @Input() userId: string;
    private userState$: Observable<User>;

    constructor(
      private store: Store<store.AppState>,
      private cdRef:ChangeDetectorRef
    ) { }
    ngOnChanges(changes: SimpleChanges) { 
        // When userId changes, it looks for a matching user in the ngrx store
        this.userState$ = this.store
                .select(state => state.user-list)                 
                .map(userList => userList[this.userId])
                .filter(user => !!user);
        this.cdRef.detectChanges();
    }
}

Alternatively, you can make userId$ an Observable and maintain the same instance instead of creating a new one each time ngOnChanges() is called:

userId$: Subject<User> = new Subject<User>();

ngOnChanges(changes: SimpleChanges) { 
    // When userId changes, it looks for a matching user in the ngrx store
    this.store
            .select(state => state.user-list)                 
            .map(userList => userList[this.userId])
            .filter(user => !!user)
            .subscribe((user) => this.userId.next(user));
}

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

OpenAPI implementation in NestJS that emphasizes the use of reusable parameters

Is it possible to reuse common parameters in the implementation of NestJS OpenAPI/Swagger? This feature would prevent me from having to clutter my endpoint with repetitive @ApiImplicitQuery decorators. ...

Assign Monday as the selected day of the week in the MUI Datepicker 6

I am currently using version 6 of the material ui Datepicker and I am trying to configure it so that the week starts on Monday. import React from "react"; import { DatePicker as DatePickerDestop } from "@mui/x-date-pickers/DatePicker"; ...

The Angular 2 HTTP GET method is throwing a type 3 error when trying to access the

i am encountering an issue while trying to retrieve a response from my asp.core api within Angular 2. The error message received is: "Object { _body: error, status: 0, ok: false, statusText: "", headers: {…}, type: 3, url: null }" Component: import { C ...

Using Angular 8 for Filtering Firebase Data

I need to implement a filter on the titles of my stored data, but I am facing an issue where the structure of the filtered data changes. The original "key" of the data gets deleted by the filter and is replaced with an index instead. Link to repository : ...

Troubleshooting problem with handling Angular modules

I'm currently working on effectively organizing folders in my Angular application. Specifically, I've set up a /components directory for shared components and a /pages directory for page-specific components. Each directory has its own module but ...

calculating the dynamic height of a document from top to bottom using Angular

Is there a way to dynamically calculate the height of each page from top to bottom in Angular? The syntax that works in JavaScript seems to give an error in Angular. console.log( (document.height !== undefined) ? document.height : document.body.offsetHeigh ...

I have encountered limitations with useFormik where it does not accept null values for initialValues, even while utilizing a validationSchema

I am currently utilizing the useFormik hook to handle my form. The userId field is a select, so by default its value is set to null. However, my validationSchema requires this field to be populated before submission. const formik = useFormik<ApiCredit ...

Direct all hash-based URLs to Angular Routes without the hash symbol being displayed

I'm in the process of upgrading from an AngularJS 1.6.x SPA to an Angular 5.x SPA while ensuring a seamless transition for my users. One of my main concerns is users who have bookmarks to the existing app which contain hashes in the URLs (e.g. exampl ...

Utilizing Database values in .css files with Vue.js and TypeScript

I am currently working on extracting a color value from the database and applying it to my external .css files. I have searched extensively online but haven't found a satisfactory solution yet. Here is the JavaScript code snippet: createBackgroundHead ...

Angular variable encounters an error while attempting to assign the returned object

Upon receiving an object from the server and attempting to assign it to a variable within an Angular component object, I am encountering an exception. Can anyone provide insight into what may be missing or causing this issue? product-component.ts import ...

rxjs iterates through an array executing each item in sequential order

Is there a way to make observables wait until the previous one has completed when they are created from an array? Any help is appreciated! export class AppComponent{ arr: number[] = [5, 4, 1, 2, 3]; fetchWithObs() { from(this.arr) ...

Managing the back button in Nativescript-Angular to toggle visibility

Struggling to toggle the visibility of an element in response to the back button event. <ActionItem icon="~/images/menu_3_dots.png" ios.position="right" android.position="right" *ngIf="isActionItemVisible"></ActionItem> construc ...

Angular Fragmentary Perspective

I have a lengthy form in angular that I am currently working on. I'm wondering if there is a way to divide it into multiple views and then link each of them back to the main view. <div class="container"> <div class="row" id="part1"> ...

Unable to determine the data type of the JSON object during the

I'm having trouble reading an Object type of json... Here is the json I'm working with: body: { "111": { "name": "name1", "status": 10000 }, "222": { "name": "name2", "status": 20000 }, "333": ...

Identifying Scroll Behavior in Ionic 4

I'm trying to figure out how to detect upwards scrolling using the following code: <ion-infinite-scroll (ionInfinite)="doInfinite($event)" scrollY="true"> <ion-infinite-scroll-content></ion-infinite-scroll-content> </ion-infin ...

Enhance your webpage design with stylish CSS formatting using Bulma cards

My HTML output is as follows: https://i.stack.imgur.com/aBdEF.jpg It seems that the footer is not matching up with the cards... The CSS component I am using looks like this: .card-equal-height { display: flex; flex-direction: column; height: 100%; ...

What methods can be employed to ensure that external stylesheets are properly loaded within the shadow DOM?

I created a new CSS utility for responsive design and built a documentation site using Angular 16 to showcase its features. To demonstrate the responsiveness, I developed a component with a resizable <iframe> where I embed the demonstration component ...

Troubleshooting with matTootip on Safari: Tips for avoiding input-text blockage

I am currently using the matTooltip feature from Angular Material for an input field. However, on Safari, the input field appears to be overlapping, making it impossible to type in. Despite my attempts to change the position of the toolTip, the issue pers ...

The `ngx-infinite-scroll` feature does not function properly on mobile devices when used in conjunction with the

I'm currently working on an Angular project that utilizes the mat-sidenav layout and routing. I came across an issue when trying to display a list of elements from a database using ngx-infinite-scroll. Following the user guide for ngx-infinite-scroll, ...

What is the functioning process of the angular method decorator?

The tutorial on creating custom decorators in Angular introduces a throttle decorator that utilizes the lodash throttle function. The implementation of this decorator can be seen below: import t from 'lodash.throttle'; export function throttle( ...