3

I'm using ngx-virtual-scroller with a additional toggle component on top. On user toggle additional items are added to virtual scroller.

This results in automatic scroll behaiviour, if items which are added are before current position. If the user is on top, additional items are added below which looks fine. If the user is in the middle it results in unexpected scrolling.

Is it possible to avoid this scrolling?

I would like to lock/freeze the screen/position.

Update: something like

const currentIndex = this.scroller.viewPortInfo.startIndex;
update();
this.scroller.scrollToIndex(currentIndex);

works more or less. It flickers. Sometimes it scrolls back not to exactly same position. So if update operation is done multiple times there is a movement.

Juri
  • 1,531
  • 2
  • 20
  • 43

3 Answers3

0
// Assuming you have a ref to the virtual scroller component
const virtualScroller = document.querySelector('ngx-virtual-scroller');

// Assuming you have a ref to the toggle component and an event handler for the toggle    
const toggle = document.querySelector('.toggle');    
toggle.addEventListener('change', handleToggleChange);    

let currentScrollPosition = 0;

function handleToggleChange() {
  // Calculate the height of items added
  const addedItemsHeight = calculateAddedItemsHeight();

  // Temporarily disable the virtual scroller's scroll events
  virtualScroller.removeEventListener('scroll', handleScroll);
    
  // Calc the new scroll position based on the prev position and the added items height    
  const newScrollPosition = currentScrollPosition + addedItemsHeight;    

  // update scroll position
  virtualScroller.scrollTo({ top: newScrollPosition });

  // Re-enable the virtual scroller
  virtualScroller.addEventListener('scroll', handleScroll);
}

function handleScroll() {
  // Update the current scroll position
  currentScrollPosition = virtualScroller.scrollTop;
}

function calculateAddedItemsHeight() {
  // Calculate and return the height of the added items
}
Rahul Prasad
  • 151
  • 1
  • 5
  • got the idea. in my case it's not working. f.e. there is no such property like scrollTop – Juri Jun 05 '23 at 11:19
0

Another way can be as follows:

  1. Add a boolean var to keep track of whether the scroll position should be frozen or not.
    frozenScrollPosition = false;
  1. When the user toggles the additional items, set frozenScrollPosition to true:
  toggleAdditionalItems() {
     // add additional items
     this.frozenScrollPosition = true;
   }
  1. Add a reference to the ngx-virtual-scroller component in your template:
    <ngx-virtual-scroller #virtualScroller [items]="items" ...></ngx-virtual-scroller>
  1. When frozenScrollPosition is true, use the scrollToIndex method of the ngx-virtual-scroller comp to scroll to the current pos:
    ngAfterViewChecked() {
      if (this.frozenScrollPosition) {
        const currentScrollPosition = this.virtualScroller.currentScrollPosition();
        this.virtualScroller.scrollToIndex(currentScrollPosition);
      }
    }
Shristi
  • 7
  • 2
Rahul Prasad
  • 151
  • 1
  • 5
  • there is no method like currentScrollPosition on VirtualScrollerComponent – Juri May 31 '23 at 12:34
  • Use viewchild in that case: ' @ViewChild(VirtualScrollerComponent) virtualScroller: VirtualScrollerComponent;' Use the below code in toggleAdditionalItems() " // Scroll to the current position const currentScrollPosition = this.virtualScroller.scrollPosition; this.virtualScroller.scrollInto(currentScrollPosition);" – Rahul Prasad Jun 02 '23 at 15:12
  • there is also no scrollPosition property – Juri Jun 02 '23 at 15:30
0

To freeze the screen position when new items are added to ngx-virtual-scroller, you can use the scrollToIndex method to scroll the view to a specific index after new items have been added. Here are the steps to implement this:

  1. Create a reference to the virtual-scroller component using the ViewChild decorator:
import { Component, ViewChild } from '@angular/core';
import { VirtualScrollerComponent } from 'ngx-virtual-scroller';

@Component({
  selector: 'app-my-component',
  template: `
    <button (click)="addItems()">Add Items</button>
    <virtual-scroller #scroller [items]="items">
      <div *ngFor="let item of scroller.viewPortItems">{{item}}</div>
    </virtual-scroller>
  `,
})
export class MyComponent {
  @ViewChild('scroller') scroller: VirtualScrollerComponent;
  items = ['Item 1', 'Item 2', 'Item 3'];

  addItems() {
    // add new items to the items array
    this.items.push('Item 4', 'Item 5', 'Item 6');

    // determine the index of the current item at the top of the view port
    const index = this.scroller.viewPortItems[0].$index;

    // scroll the view to the same index to freeze the screen position
    this.scroller.scrollToIndex(index);
  }
}
  1. In the addItems method, add the new items to the items array.
  2. Get the index of the current item at the top of the view port using this.scroller.viewPortItems[0].$index.
  3. Scroll the view to the same index using this.scroller.scrollToIndex(index) to freeze the screen position.
Raymond
  • 550
  • 1
  • 5
  • 14