primefaces / primeng

The Most Complete Angular UI Component Library
https://primeng.org
Other
9.95k stars 4.52k forks source link

p-table: Virtual Scroll, Lazy Load table hangs when sorting, after scrolling to the bottom of the table #13494

Open SaajRP opened 12 months ago

SaajRP commented 12 months ago

Describe the bug

The table hangs and the page becomes unresponsive on a virtual scroll, lazy load table, when sorting after scrolling to the bottom of the table when there is sufficiently large totalRecords (~10000)

This issue does not happen for the same table with the same number of totalRecords when sorting when scrolled at the top of the table

Environment

macOS Ventura 13.5

Windows 10 Version 22H2

Reproducer

https://stackblitz.com/edit/oetsny-rdsoxe?file=src%2Fapp%2Fdemo%2Ftable-virtual-scroll-lazy-demo.ts

Angular version

16.X.X, 17.X.X

PrimeNG version

16.X.X, 17.2.0

Build / Runtime

Angular CLI App

Language

TypeScript

Node version (for AoT issues node --version)

18.12.0

Browser(s)

No response

Steps to reproduce the behavior

Expected behavior

cravay commented 9 months ago

We're affected by this bug as well. The table seems to hang in Table.scrollToVirtualIndex. As a workaround, it seems to be possible to manually scroll to the top of the table like this:

<p-table
  ...
  (onSort)="onSort()"
  [resetPageOnSort]="false"
>
@ViewChild(Table) table!: Table;

onSort(): void {
  // Scroll to the top.
  this.table.scrollTo({ top: 0 });

  // Dispatch scroll event to update scroller state.
  this.table.scroller
    ?.getElementRef()
    ?.nativeElement?.dispatchEvent(new Event('scroll'));
}

Demo: https://stackblitz.com/edit/oetsny-xno6ns?file=src%2Fapp%2Fdemo%2Ftable-virtual-scroll-lazy-demo.ts

SaajRP commented 8 months ago

This remains a problem as of PrimeNg 16.9.0

SaajRP commented 8 months ago

I've done a few tests with the code @cravay suggested

onSort(): void {
    // Scroll to the top. Any of the below function call can be used
    //this.table?.scrollToVirtualIndex(0);
    //this.table?.scrollTo({ top :0 });
    //this.table?.scroller?.scrollToIndex(0);
    this.table?.scroller?.getElementRef()?.nativeElement?.scrollTo({ top: 0 });
    // Dispatch scroll event to update scroller state. Not dispatching the event will stop this from working
    this.table?.scroller
      ?.getElementRef()
      ?.nativeElement?.dispatchEvent(new Event("scroll"));
  }

After testing it appears that not dispatching a new Event to the nativeElement in scroller.ts will cause the issue

That would imply this event is not being updated otherwise

SaajRP commented 8 months ago

Tried an upgrade to Angular 17 and PrimeNg 17.0.0. This remains a problem

SaajRP commented 6 months ago

This remains a problem as of PrimeNg 17.2.0

esaAtbeconfig commented 5 months ago

@SaajRP I have made the ugliest code ever to get it working, As sorting works fine from top or with few lines; I have a try with lowering displayed data before sorting than recover it after scrolling using this horrible code :

`private setSortFunction() { if (!this.table) { setTimeout(() => this.setSortFunction(), 100); } else { const self = this; this.table.sort = function (event: any) { if (this.sortMode === 'single') { this._sortOrder = this.sortField === event.field ? this.sortOrder * -1 : this.defaultSortOrder; this._sortField = event.field;

      if (this.scroller) {

        // get the displayed data
        const displayed = this.scroller?.items?.slice(
          this.scroller.first,
          this.scroller.last
        ) as Dataline[];
        const count = this.scroller?.last - this.scroller?.first;

        // it stores the current value and push only few lines to keep the columns alignment
        // the datalineService expose a dataline$ observable that is used as the table value
        const datalines = self.datalineService.forceUpdate(displayed);
        // keep existing calls
        this._first = 0;
        this.firstChange.emit(this._first);
        // reset the scroll to top as it works well with scroll at top
        this.resetScrollTop();
        // move the scroller so translate3d is at 0,0
        this.scroller?.setContentPosition({ first: 0, last: count });

        setTimeout(() => {
          // set the full data back
          self.datalineService.forceUpdate(datalines);
          // launch the sort
          this.sortSingle();
          // keep existing calls
          if (this.isStateful()) {
            this.saveState();
          }
        });
      }
    }
    // keep existing call
    this.anchorRowIndex = null;
  };
}

}`

SaajRP commented 4 months ago

This is no longer a problem as of PrimeNg 17.10.0

esaAtbeconfig commented 4 months ago

This is no longer a problem as of PrimeNg 17.10.0

Trying with only 17.10.0 update did not solve the problem on my side.

SaajRP commented 4 months ago

This is no longer a problem as of PrimeNg 17.10.0

Trying with only 17.10.0 update did not solve the problem on my side.

@esaAtbeconfig try and compare your code with the StackBlitz project, I have linked under the Reproducer section. We may have different PrimeNg table properties, Angular versions etc