I don't understand why the child component's change detection runs in this scenario:
import { Component, ChangeDetectionStrategy } from '@angular/core'
@Component({
selector: 'app-root',
template: `
<cmp [ticks]="ticks" (update)="onUpdate($event)"></cmp>
`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent {
ticks = 0;
onUpdate(event) {
console.log(this.ticks);
}
}
import { Component, ChangeDetectionStrategy, OnInit, Input, Output, EventEmitter, OnChanges } from '@angular/core';
@Component({
selector: 'cmp',
changeDetection: ChangeDetectionStrategy.OnPush,
template: `<p>Number of ticks: {{ticks}}</p>
`
})
export class CmpComponent implements OnInit, OnChanges {
@Input('ticks') ticks: number;
@Output() update: EventEmitter<number> = new EventEmitter();
ngOnInit() {
setInterval(() => {
this.ticks++;
this.update.emit(this.ticks);
}, 1000);
}
ngOnChanges() {
console.log('changed');
}
}
When I run this 'Number of ticks' is updated in the child view.
When I remove listening to the event in the parent it does not update the view.
What I understand is the following:
Because the parent implements the OnPush strategy it triggers change detection when it listens to the event that is emitted from the child. On receiving the event it does not alter 'tick' and therefore the child component's @Input() is not updated. Yet the child component which also implements OnPush strategy updates its view. It therefore acts as if its @Input changed.
From my research:
With the OnPush strategy the change detection happens for a component if:
- a bound event is received on the component itself.
- an @Input() was updated
- | async pipe received an event
- change detection was invoked "manually"
None of these seem to be applicable to the child component.
Any explanations? Much appreciated.