New components rendered by CdkVirtualForOf are pristine by default.
New components created by CdkVirtualForOf within the <cdk-virtual-scroll-viewport> inherit internal state of recycled views by default.
https://stackblitz.com/edit/angular-virtual-scrolling-with-component-state
Angular CLI: 7.3.8
Node: 11.12.0
OS: win32 x64
Angular: 7.2.12
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, platform-server, router
... service-worker
Package Version
-----------------------------------------------------------
@angular-devkit/architect 0.13.6
@angular-devkit/build-angular 0.13.6
@angular-devkit/build-optimizer 0.13.6
@angular-devkit/build-webpack 0.13.6
@angular-devkit/core 7.1.4
@angular-devkit/schematics 7.1.4
@angular/cdk 7.3.7
@angular/cli 7.3.8
@angular/pwa 0.11.4
@ngtools/webpack 7.3.6
@schematics/angular 7.1.4
@schematics/update 0.13.8
rxjs 6.4.0
typescript 3.2.4
webpack 4.29.0
Surely this is the very intent of view recycling, but it seems very strange that the default behaviour of *cdkVirtualFor is very different from *ngFor: my bound parameters changed, the data rendered via the @Input() changed, so why didn't the internal state reset?
It's more than _template_ caching, which most of us would take to mean the HTML: it caches whole components and internal state.
Obviously, setting templateCacheSize: 0 fixes this problem.
Maybe simply highlighting this in the documentation might help, since you have to read between the lines to understand what's happening? Perhaps I'm the only one with this expectation. 🤷♂️
Hi Michael, it is not a defect of Angular. Virtual scroll uses cache to reuse components, but your component is not reusable. Look at my explanation for another issue - you have the same case
https://github.com/angular/components/issues/16330#issuecomment-514591282
Solution can look like this (but state will be lost):
@Component({
selector: 'hello',
template: `<h1 [class.active]="active">Data Item {{_item}}</h1>`,
styles: [
`.active {background-color: red; color: white}`,
`h1:hover { background-color: lightblue }`
]
})
export class HelloComponent {
@Input() set item(item: number) {
this._item = item;
this.active = false;
}
_item: number;
active: boolean = false;
toggle = () => this.active = !this.active;
}
@ArtemKlots While I agree that this is not a defect by virtue of it being a design choice, I still think it _might_ be a good idea to highlight this behaviour in the documentation more clearly, which was the point of this ticket.
I suppose I could do that at this point.
I got the same exact "bug" today. The documentation at https://material.angular.io/cdk/scrolling/overview#virtual-scrolling should definitively be updated with information about this behavior.
Most helpful comment
Hi Michael, it is not a defect of Angular. Virtual scroll uses cache to reuse components, but your component is not reusable. Look at my explanation for another issue - you have the same case
https://github.com/angular/components/issues/16330#issuecomment-514591282
Solution can look like this (but state will be lost):