primeng icon indicating copy to clipboard operation
primeng copied to clipboard

p-table: Restore scroll position or disable auto scroll

Open schokolateur opened this issue 2 years ago • 8 comments

Describe the feature you would like to see added

Hi there,

when changing data of a table, the table always scrolls to the top. It would be great, if i could disable that. For now, is there any change to find out the virtual index of the first visible row in the table?

Thanks

Is your feature request related to a problem?

No response

Describe the solution you'd like

No response

Describe alternatives you have considered

No response

Additional context

No response

schokolateur avatar Mar 24 '23 07:03 schokolateur

having the same problem. Any update on this?

kaspaddy avatar Apr 17 '23 08:04 kaspaddy

Having the same problem

Rdem2601 avatar Jun 22 '23 11:06 Rdem2601

Having the same problem, don't have a hacky fix either :)

FrankPSteel avatar Jul 13 '23 14:07 FrankPSteel

For angular my really hacky fix is acutally the following:

@ViewChild('table') table: Table; private scrollSubscription: any; private tmpScrollPos: number = 0; private lastScrollPos: number = 0;

... at some place where table variable has been set: if (this.table && this.table.scroller) { this.scrollSubscription = this.table.scroller.onScroll.subscribe({ next: (result: any) => { this.tmpScrollPos = result.originalEvent.srcElement.scrollTop; }, }); }

... at a point where i need to restore the position, i save the tmpScrollPos: this.lastScrollPos = this.tmpScrollPos;

then i update the table data: ... this.tableData = [...this.tableData];

and to be sure to get a fresh ui i have to hack again. I use the virtualScrollITemSize for this: <p-table #table [scrollable]="true" [virtualScroll]="true" [rows]="30" [scrollHeight]="'flex'" [virtualScrollItemSize]="drh()" [value]="tableData"> drh(): number { return 37 + this.drhFix; // 37 is my fixed row height...drh is for dynamic row height }

after updating the table data i do: this.drhFix = 1; setTimeout(() => { this.drhFix = 0; });

and at the end: setTimeout(() => { this.table.scrollTo({ left: 0, top: this.lastScrollPos, behavior: 'instant', }); });

not nice, and on large tables you will see a fast jump, but its a hack and it actually works for me. I have added an css animation to highlight the row i jumped to, to focus the eye on the row which helps, but i still hope to get a fix on the main table component...

schokolateur avatar Jul 14 '23 06:07 schokolateur

@schokolateur thanks I will use your hacky trick for now. I hope there will be an option no autoscroll by updating data with a virtual scroller or something. But thanks you saved my day 💯 !

FrankPSteel avatar Jul 14 '23 10:07 FrankPSteel

But a fix would be better, it is lagging when I'm dragging a row :(

FrankPSteel avatar Jul 19 '23 13:07 FrankPSteel

I also confirm the issue still persists.

Adding simple stackblitz to demonstrate the issue: https://stackblitz.com/edit/n34vgd?file=src%2Fapp%2Ftable-vertical-scroll-demo.html Just scroll somewhere in the table and click on the remove button on the right side.

When virtualscroll is used on a table then removal of any item from the table will cause table to scroll to the top, and this is not desired. When virtualscroll is not used then this issue is not reproducible.

srnec avatar Aug 28 '24 08:08 srnec

I've been using this workaround for a while, not sure if it's still working on the latest version, but it basically captures the scroll position before modifying the css 'contain' property, then restores it.

The code patches the Scroller class and should be called during initialization, such as putting it in main.ts.

import { Scroller } from 'primeng/scroller';
import { ElementRef } from '@angular/core'
import { DomHandler } from "primeng/dom";

Scroller.prototype.calculateAutoSize = function() {
  if (this._autoSize && !this.d_loading) {
      Promise.resolve().then(() => {
          if (this.contentEl) {
              this.contentEl.style.minHeight = this.contentEl.style.minWidth = 'auto';
              this.contentEl.style.position = 'relative';

              let originalScrollPosition = this.elementViewChild.nativeElement.scrollTop;  // ADDED

              (<ElementRef>this.elementViewChild).nativeElement.style.contain = 'none';

              const [contentWidth, contentHeight] = [DomHandler.getWidth(this.contentEl), DomHandler.getHeight(this.contentEl)];
              contentWidth !== this.defaultContentWidth && ((<ElementRef>this.elementViewChild).nativeElement.style.width = '');
              contentHeight !== this.defaultContentHeight && ((<ElementRef>this.elementViewChild).nativeElement.style.height = '');

              const [width, height] = [DomHandler.getWidth((<ElementRef>this.elementViewChild).nativeElement), DomHandler.getHeight((<ElementRef>this.elementViewChild).nativeElement)];
              (this.both || this.horizontal) && ((<ElementRef>this.elementViewChild).nativeElement.style.width = width < <number>this.defaultWidth ? width + 'px' : this._scrollWidth || this.defaultWidth + 'px');
              (this.both || this.vertical) && ((<ElementRef>this.elementViewChild).nativeElement.style.height = height < <number>this.defaultHeight ? height + 'px' : this._scrollHeight || this.defaultHeight + 'px');

              this.contentEl.style.minHeight = this.contentEl.style.minWidth = '';
              this.contentEl.style.position = '';
              (<ElementRef>this.elementViewChild).nativeElement.style.contain = '';

              this.elementViewChild.nativeElement.scrollTop = originalScrollPosition;      // ADDED
          }
      });
  }
}

omnight avatar Aug 28 '24 08:08 omnight

Today, I encountered the same issue when using the p-table with virtual scroll: every time I added multiple items to the table, it would reset the scroll position to the top. To fix this, I added the max-height style with the same value as scrollHeight to the .p-scroller.p-scroller-inline class.

.p-scroller.p-scroller-inline {
  max-height: 400px; // p-table scrollHeight value
}

jeanfsantos avatar Sep 13 '24 17:09 jeanfsantos

@jeanfsantos this works, thank you 🙏

MohRaouf avatar Sep 14 '24 20:09 MohRaouf

why was this issue closed if it has not been properly fixed?? It's still an issue in v19

gianluca-moro avatar May 28 '25 13:05 gianluca-moro

@jeanfsantos Thanks!

maksimis avatar Nov 01 '25 06:11 maksimis

@jeanfsantos Thanks!

@maksimis Which version of PrimeNg do you use? In my case the table is using p-virtualscroller class not p-scroller and it already has height set with the same value as scrollHeight so the @jeanfsantos hack does not work.

Emkacf avatar Nov 12 '25 14:11 Emkacf

@jeanfsantos Thanks!

@maksimis Which version of PrimeNg do you use? In my case the table is using p-virtualscroller class not p-scroller and it already has height set with the same value as scrollHeight so the @jeanfsantos hack does not work.

Hello @Emkacf Could you tell us what version you are using?

If you look at this code: https://github.com/primefaces/primeng/blob/master/packages/primeng/src/scroller/scroller.ts#L38

Technically you can use any of these selectors to achieve the same behavior. You can also check if you're using "height" or "max-height." To make it work, use "max-height." 🙂

jeanfsantos avatar Nov 12 '25 16:11 jeanfsantos

@jeanfsantos I think it is not working for me because I have bit different case with the scroll. We have internal tabs that are working on custom routing strategy and each time I navigate to another tab (so another url) and go back the scroll goes to the top but the items are not loaded properly until I physically scroll the table. The workaround for this is calling

this.tableRef()?.scrollToVirtualIndex(10); this.tableRef()?.scrollToVirtualIndex(0);

On router event but then it will be always on top and I would like to preserve the original state. I need to call scrollToVirtualIndex twice because calling it with 0 at the beginning doesn't work. Need to call with some index first and then go to 0...

Emkacf avatar Nov 13 '25 13:11 Emkacf