p-table: Restore scroll position or disable auto scroll
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
having the same problem. Any update on this?
Having the same problem
Having the same problem, don't have a hacky fix either :)
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 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 💯 !
But a fix would be better, it is lagging when I'm dragging a row :(
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.
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
}
});
}
}
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 this works, thank you 🙏
why was this issue closed if it has not been properly fixed?? It's still an issue in v19
@jeanfsantos Thanks!
@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.
@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 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...