Apparently I have a huge missunderstanding about angular’s internals.
Consider the following situation:
@Component({
selector: 'banana',
template: ` <h1>We have {{ item.x }} bananas.</h1> `,
})
export class Banana implements {
@Input() item: { x: number } = { x: 0 };
}
@Component({
selector: 'app-root',
template: `<banana [item]="item"></banana>`,
})
export class AppComponent {
protected item = { x: 0 };
constructor() {
setInterval(() => {
this.item.x = Math.random();
}, 1000);
}
}
Up to this day I thought that this would not work (i.e. the changed item.x value would not be displayed), because I learned that angular change detection would do shallow comparisons per default.
Indeed, in the docs we find the following:
Modifying object references. In case an input receives a mutable object as value and you modify the object but preserve the reference, Angular will not invoke change detection. That’s the expected behavior because the previous and the current value of the input point to the same reference.
To my surprise, the example above does indeed work. My question is: Why? What exactly causes the view to update and what relation does this reason have with change detection?
This blog post talks about a similar situation (where the author renders the first but not the last name nested property). But modifying my example above to display the changes:
[...] implements OnChanges {
[...]
ngOnChanges(changes: SimpleChanges): void {
console.log(changes);
}
yields no logs – in my undestanding this means that change detection did not detect any changes (as expected due to the cited paragraph from the docs).
So what is going on here?