After testing I noticed I get the same error you are experiencing, however this only occurs if you have them nested in the same component. If you add a cdk-virtual-scroll in a child component then you will have no problem having multiple nested within each other.
Example:
parent-component.html
<cdk-virtual-scroll-viewport itemSize="50">
<div *cdkVirtualFor="let parent of parents">
<h4>{{ parent.name }}</h4>
<child-component [children]="children"></child-component>
</div>
</cdk-virtual-scroll-viewport>
child-component.html
<cdk-virtual-scroll-viewport itemSize="50">
<div *cdkVirtualFor="let child of children">
<p>{{ child.name }}</p>
</div>
</cdk-virtual-scroll-viewport>
Additional Advice:
According to the CDK documentation you should be using it like this. This is the same answer as above but with correct layout.
Example:
parent-component.html
<cdk-virtual-scroll-viewport itemSize="50">
<ion-list>
<ng-container*cdkVirtualFor="let parent of parents">
<h4>{{ parent.name }}</h4>
<child-component [children]="children"></child-component>
</ng-container>
</ion-list>
</cdk-virtual-scroll-viewport>
child-component.html
<cdk-virtual-scroll-viewport itemSize="50">
<ion-list>
<ng-container*cdkVirtualFor="let child of children">
<p>{{ child.name }}</p>
</ng-container>
</ion-list>
</cdk-virtual-scroll-viewport>
Additional Performance Tips:
Please look into using the following for greater performance, it is especially noticeable on mobile, weather it is a website or within a WebView such as ionic.
cdk-virtual-scroll-viewport
- appendOnly: When enabled this will append newly created items in your list to persists. When disabled angular will destroy and re-create components on scroll. This is disabled by default
- minBufferPx: The minimum amount of content the viewport buffer has to render
- maxBufferPx: Tells the viewport how much more content to render when it detects more content needs to be rendered.
- autosize: This is an experimental feature however in my testing it seems more performant than setting a size if the size of your list items are different. (Only found in cdk/experimental)
cdVirtualFor
- trackBy: Tracks already rendered data to avoid extra change detections which in turn may run extra functions etc based on your code setup
- templateCacheSize: This by default sets the value to 20. Meaning the last 20 elements scrolled out of view will be cached for fast rendering on scroll. If your elements have very little logic then increasing this can increase your scroll performance. However, if your elements have heavy logic then it may be better to disable caching by setting the value to 0.