Consider this plunker
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: 'my-app-n1',
template: `
<my-app-n2 [from2]="from1"></my-app-n2>
<div>
{{from1.name}}
<input type="button" value="n1" (click)="changen1()">
</div>
`,
})
export class App2 {
@Input() from1;
ngDoCheck() {
console.log('do check 1 ', this.from1);
}
ngOnChanges(changes: any) {
console.log('n1 change ', changes);
}
changen1() {
this.from1 = {'name': 'name1-2'}
}
}
@Component({
selector: 'my-app',
template: `
<my-app-n1 [from1]="from"></my-app-n1>
<input type="button" value="root" (click)="changen0()">
`,
})
export class App {
from: any;
constructor() {
this.from = {'name': 'name0'}
}
ngOnChanges(changes: any) {
console.log('n0 change ', changes);
}
changen0() {
this.from.name = 'name-0-2-2'
}
}
Notice that App2
uses ChangeDetectionStrategy.OnPush
When changen0
is clicked I expect ngOnChanges
to not be called (since no new reference is assigned) and ngDoCheck
to be called with this.from1
to have the data {'name': 'name0'}
and the view still displaying name0
But instead
ngDoCheck
is called with this.from1
equal {'name': 'name-0-2-2'}
and the view is displaying name0
My question is the following
Why is the property this.from1
changed?
And if the model is changed why is the view inconsistent with the model?
You're using ChangeDetectionStrategy.OnPush
for the App2
which means that CD will not be triggered for App2
unless the input binding [from1]="from"
is updated.
So when you update the name
property here the name
is updated:
changen0() {
this.from.name = 'name-0-2-2'
}
you don't update the reference to this.from
and hence change detection is not triggered for the App2
so you don't see the change in the HTML. ngOnChanges
is not called as well.
ngDoCheck is called with this.from1 equal {'name': 'name-0-2-2'}
ngDoCheck
doesn't mean your component being checked. It's called when Angular checks the parent component. Read this article for more information: