CirclonGroup / angular-tree-component

A simple yet powerful tree component for Angular (>=2)
https://angular2-tree.readme.io/docs
MIT License
1.1k stars 494 forks source link

virtualScroll sometimes is completely blank / empty #717

Open philipphutterer opened 5 years ago

philipphutterer commented 5 years ago

Sometimes the tree is completely empty when virtualScroll is activated. After some debugging i found out that renderedNodesMaxLength in tree-virtual-scroll.model.ts is not an integer but a float. This buggy behaviour did not occur anymore after ceiling renderedNodesMaxLength. Maybe because of some strange combinations of nodeHeight and treeHeight this value will not be an integer and the test some lines later fails. What was the actual thought behind this check?

Regards

vincent-cm commented 3 years ago

same here, When scrolling, the content become to empty for a while

Screenshot-2020-11-13-at-11-24-47
EA-EKB commented 3 years ago

The problem still exists(

vinodsantharam commented 2 years ago

We had the same issue. We did this trick and it works well (even the node.scrollToView() works perfectly after):

<div class="tree-view-container" *ngIf="items.length > 0"> <!-- the trick is to wrap and hide with ngIf -->
    <tree-root
        [nodes]="items"
        [options]="options"
    >
    ...
   </tree-root>
</div>

We load the data asynchronously and before fetching the API we worked with mocked data. There weren't absolutely no issues. Problems came just after calling the API.

Hopefully, that will help you guys.

Kexplx commented 2 years ago

Same here.

ihorbershov commented 1 month ago

I was able to reproduce the defect consistently this way: (for angular version: 13.3.0 and angular-tree-component version: 11.0.4)

Main component:

<input  type="checkbox" id="checkbox1" [checked]="showContainer" (change)="showContainer = !showContainer"/>
<div *ngIf="showContainer">
  <app-tree-container></app-tree-container>
</div>

tree-container.component.html

<input  type="checkbox" id="checkbox2" [checked]="showTreeRoot" (change)="showTreeRoot = !showTreeRoot"/>
<div *ngIf="showTreeRoot">
    <tree-root #tree [nodes]="nodes" [options]="options"></tree-root>
</div>

tree-container.component.ts

nodes: any = [];
options = { useVirtualScroll: true };
setDataToTree() { this.nodes = [ { id: 1, name: 'root1' }]; }

If the setDataToTree() method is called from the constructor or ngOnInit(), everything works correctly.

If the setDataToTree() method is called from ngAfterViewInit(), the defect appears after clicking checkbox1.

If the setDataToTree() method is called from setTimeout(() => { ... }, 100), the defect appears when the page is opened.

Clicking checkbox2 "fixes" the defect in both cases.

The workaround that worked in my case is based on @vinodsantharam's solution:

@ViewChild("tree") tree: TreeComponent;

ngAfterViewInit(): void {
  loadAndSetTreeData();
  setTimeout(() => this.checkIfTreeIsEmptyAndRefresh(), 100);
}

private checkIfTreeIsEmptyAndRefresh(): void {
  const isDataEmpty = this.nodes.length === 0;
  if(isDataEmpty) return;

  const isTreeEmpty = (this.tree.viewportComponent as any).elementRef.nativeElement.querySelector("tree-node") === null;
  if(!isTreeEmpty) return;

  // There should be nodes, but the tree is empty.
  // Hide and show the tree again so that the data appears.
  this.showTreeRoot = false;
  setTimeout(() => { this.showTreeRoot = true; }, 0);
}
ihorbershov commented 1 month ago

Please ignore the way I reproduced the defect from my previous comment. I forgot to specify the height of the container, and the documentation clearly states that the height is required:

To use this option, one must supply the height of the container, and the height of each node in the tree.

https://circlongroup.github.io/angular-tree-component -> Guides -> Large Trees & Virtual Scroll

I'll leave the previous comment as it is in case someone else makes the same mistake.

However, I have not found a way to avoid the defect in the main application. For some reason, the viewportHeight variable from the TreeVirtualScroll class is sometimes equal to zero. So the getViewportNodes method returns an empty array and the tree remains empty. https://github.com/CirclonGroup/angular-tree-component/blob/master/projects/angular-tree-component/src/lib/models/tree-virtual-scroll.model.ts#L130

I currently use the following workaround:

private checkIfTreeIsEmptyAndRefresh(): void {
  // Check if the viewportHeight variable has an incorrect value.
  if(this.tree?.viewportComponent?.virtualScroll?.viewportHeight === 0)
  {
    // Call the sizeChanged method to force virtualScroll to recapture viewportHeight.
    this.tree.sizeChanged();
  }
}