0

I have a very, very bare minimal tree, that sometimes needs to render thousands upon thousands of elements. This results in some very poor performance, so the site gets quite laggy. I instead opted to try out cdk-virtual-scroll-viewport, but I cannot get it to work, because I'm using ngTemplateOutlet. Example:

<ul>
    <ng-template #recursiveList let-root>
        <li *ngFor="let item of root; trackBy:item?.id">

            <!-- Show the actual elements, including + and - to expand/contract the tree -->

            <ul [ngClass]="item?.expanded ? '' : 'hide'" *ngIf="item?.children && item?.children.length > 0">
                <ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: item?.children }"></ng-container>
            </ul>
        </li>
    </ng-template>
    <ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: root }"></ng-container>
</ul>

My root array looks a bit like this:

[{
  id: "aec04ef4-fc6a-481f-a12d-0ce987d494b3",
  expanded: true,
  children: [{
    id: "cbf9e862-e932-410f-ad84-ed0a5ec1917a",
    expanded: false,
    children: []
  }]
}]

I tried simply doing this:

<ul>
    <ng-template #recursiveList let-root>
        <li *cdkVirtualFor="let item of root; trackBy:item?.id">

            <!-- Show the actual elements, including + and - to expand/contract the tree -->

            <ul [ngClass]="item?.expanded ? '' : 'hide'" *ngIf="item?.children && item?.children.length > 0">
                <ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: item?.children }"></ng-container>
            </ul>
        </li>
    </ng-template>

    <cdk-virtual-scroll-viewport style="height: 750px" itemSize="50">
        <ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: root }"></ng-container>
    </cdk-virtual-scroll-viewport>
</ul>

So basically added the cdk-virtual-scroll-viewport element and used cdkVirtualFor instead of ngFor, but I get an error saying:

No provider for CdkVirtualScrollViewport

Which I guess is a bug, since it hasn't been closed: https://github.com/angular/components/issues/15277

Any idea how to adapt my existing code? The biggest problem I face, is the hide/unhide part, because it uses ng-container that for some reason won't work.

MortenMoulder
  • 6,138
  • 11
  • 60
  • 116

1 Answers1

0

After trying various CDK virtualization methods and never getting satisfactory results, I built a custom component for this.

https://github.com/gjcampbell/ooffice/tree/master/projects/of-tree

I recommend using a library (mine has the best performance I know of), or if you'd rather stick to your current path, then do this:

  1. On your data, store hierarchy info such as each item's depth and parent
  2. Recurse through the data and create a flat list from the hierarchical data
  3. Render the flat list without recursive templates. Use the depth to determine indentation. Pass to cdkVirtualFor only items whose parent is null or expanded.
sledgebox
  • 996
  • 8
  • 12