0

I am setting a value from the parent component and changing it immediately. In the child component, change detection executes only once.

Stackblitz code base

Parent's code: HTML

<h1>Parent Component</h1>
<p>Contents of the parent component</p>
<button (click)='parentClickEvt()'>Parent Button</button>
<child [message]="msg" (informParent)="parentWillTakeAction($event)"></child>

Parent's code: TS

export class ParentComponent {

  msg: string="testing";

  parentWillTakeAction(message) {
    this.messageFromChild = message;
  }

  parentClickEvt() {
    this.msg = "Message from parent to child";
    this.msg = "India";
    this.msg = "India, ASIA";
    this.msg = "JAPAN";
    this.msg = "JAPAN, ASIA";
  }
}

Child's code: TS

export class ChildComponent implements OnInit {

  @Input() message: string;
  @Output() informParent = new EventEmitter();

  ngOnChanges(simpleChanges: SimpleChanges) {
    console.log(simpleChanges.message.currentValue)
  }
}

Executing parentClickEvt method from parent is changing msg value 4 times. In child component, ngOnChanges is supposed to execute 4 times. But it is only executing once with the latest value.

Please suggest how ngOnChanges should execute according to all changes

2
  • 1
    You're using the wrong tool for the thing you want to accomplish. If you would like to pass a stream of values over time, use RXJS stream. ChangeDetection is for DETECTING CHANGES, so the most important value is the last one. Change detection is not free, so it's optimized to not run if it's not needed. JavaScript is synchronous, so there's no way to run changedetection between your assignment calls. Commented Jul 28, 2024 at 8:43
  • 1
    Exactly that 👆 Change detection runs as few as possible for performance purposes. It's an expensive thing to do. So just the latest update of the value is used in the next change detection cycle. You can force to run the change detection mechanism as v-pat mentions in his answer. But I can't find a reason why one would want to do that. It's a very weird thing to do tbh. You can share in another question what do you want to use case you want to achieve and I'm sure there will certainly be a much better way to do so :) Commented Jul 28, 2024 at 19:28

1 Answer 1

0

First implement OnChanges on child component.

Change detection is not working because you are changing value of msg without letting previous change detection to be completed.

I would suggest to change the approach of this rapid reassignment of values if possible, However I have a workaround. see if you can use it.

import { Component, ChangeDetectorRef } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  messageFromChild: string = '';
  msg: string = 'testing';

  constructor(private changeDetectorRef: ChangeDetectorRef) {}

  parentWillTakeAction(message: any) {
    this.messageFromChild = message;
  }

  async parentClickEvt() {
    this.msg = 'Message from parent to child';
    await this.detectChanges();
    this.msg = 'India';
    await this.detectChanges();
    this.msg = 'India, ASIA';
    await this.detectChanges();
    this.msg = 'JAPAN';
    await this.detectChanges();
    this.msg = 'JAPAN, ASIA';
  }

  detectChanges(): Promise<void> {
    return new Promise((resolve) => {
      this.changeDetectorRef.detectChanges();
      resolve();
    });
  }
}

By this way you will be able to catch change in ngOnChanges of child component.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.