I am using angular 9+ and i am little confused of the behavior of ngOnChanges life cycle.
What I am trying to do
I have a asynchrounous operation which sets a value (Object type) to the child component using @Input() decorator. The code is as below. (Stackblitz Here)
parent.ts
import { AfterViewInit, Component, VERSION, ViewChild } from '@angular/core';
import { ChildComponent } from './child/child.component';
import { of } from 'rxjs';
import { delay } from 'rxjs/operators';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit {
@ViewChild(ChildComponent) childComponent: ChildComponent;
data = { value: null };
constructor() {}
ngAfterViewInit() {
const foo = of([1])
.pipe(delay(500))
.subscribe(subscriber => {
this.data = { value: 123 };
this.childComponent.printState();
});
}
}
Parent.Html
<app-child [data]="data"></app-child>
Child Component
import { Component, Input, OnChanges } from '@angular/core';
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnChanges {
@Input() data = null;
constructor() {}
ngOnChanges(changes) {
console.log('ngOnChanges');
}
printState() {
console.log('printState');
console.log(this.data.value);
}
}
What i am trying to is , as soon as i change the value, i am trying to print the value of the set value by using a view child reference as shown above.
Ideally the sequence should have been
ngOnChanges // initial value
ngOnChanges // after value set
printState // after calling printState()
but i see
ngOnChanges
printState
ngOnChanges
in the console which is pretty consfusing. Why is ngOnChanges nor fired immediately. Why is it taking time. Can someone explain.
Thanks and stay safe :)
When you update any variable bound to @Input()
as you are doing in ngAfterViewInit
of AppComponent
, the change detection will be scheduled by Angular to run just before view rendering and not immediately after assignment.
Hence, the code in ngAfterViewInit
will execute first, and code in ngOnChanges
will be invoked by Angular in next tick.
Yes, in summary, change detection is asynchronous.