The main function of the virtual viewport is to keep track of scroll events and notify you which elements are currently on screen. Using this information, you can modify the datasource of the tree to only be the nodes that are on screen.
The problem is that right now, the viewport really only works well with items of a consistent height. When you expand a node of the tree, that node has a height that is inconsistent with the rest of the closed ones. To get around this, you may be able to add the child nodes to the virtual viewport's datasource whenever a node is expanded.
For now, I will ignore the expanded node problem.
To get basic virtual scrolling with the tree, add this to your template:
<cdk-virtual-scroll-viewport itemSize="48" style="height: 200px;">
<ng-container *cdkVirtualFor="let item of fullDatasource"></ng-container>
<mat-tree [dataSource]="dataSource" [treeControl]="treeControl">...</mat-tree-node>
</mat-tree>
</cdk-virtual-scroll-viewport>
We create the viewport, telling it the size of each node. We then add the virtualForOf
, passing in the fullDatasource so that the viewport knows how tall it needs to be. This might be cheating a bit because I believe the intended use of virtualForOf
is that the template includes the items to be scrolled, but keeping it empty seems to work.
The only thing left is to make sure the tree's datasource is only the visible items of the full datasource. We'll change how we declare it initially in the constructor, but this is the more exciting part:
ngAfterViewInit() {
this.virtualScroll.renderedRangeStream.subscribe(range => {
console.log(range, 'range')
this.dataSource.data = this.fullDatasource.slice(range.start, range.end)
})
}
We subscribe to the renderedRangeStream
which emits a range whenever the scroll changes. Whenever that happens, we simply set the datasource equal to the appropriate slice!
Stackblitz with result Hopefully this is enough to get you started!