rintoj / ngx-virtual-scroller

Virtual Scroll displays a virtual, "infinite" list.
https://rintoj.github.io/ngx-virtual-scroller
MIT License
979 stars 295 forks source link

IGNORE: This pull request ended up in wrong repository #551

Closed varadero closed 1 year ago

varadero commented 1 year ago

I am using very simple HTML essentially copy/paste from the samples here. I start with 50 items and I have a button to add more (random amount) items. After scroll to the bottom and click the button to add more items, the number of items on the screen reduces in half. I am using angular 15.2.7 and @iharbeck/ngx-virtual-scroller 15.2.0

Stackblitz - https://stackblitz.com/edit/angular-rryu4u?file=src%2Fmain.ts

Everything is in main.ts file so I am pasting it here for reference:

import 'zone.js/dist/zone';
import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { bootstrapApplication } from '@angular/platform-browser';
import { VirtualScrollerModule } from '@iharbeck/ngx-virtual-scroller';

@Component({
  selector: 'my-app',
  standalone: true,
  imports: [CommonModule, VirtualScrollerModule],
  template: `
    <ul>
      <li>Scroll to the bottom</li>
      <li>Click on "Add more items" butotn</li>
      <li>Scroll to the bottom</li>
      <li>Repeat until about 70+ items are added - the number of items shown in the cirtual scroller is reduced in half</li>
    </ul>
    <virtual-scroller #scroll [items]="items">
      <div class="grid-rows">
        <div *ngFor="let item of scroll.viewPortItems" class="grid-row">
          <div class="grid-row-id">{{item.id}}</div>
          <div class="grid-row-name">{{item.name}}</div>
          <div class="grid-row-email">{{item.email}}</div>
          <div class="grid-row-date">{{item.date}}</div>
        </div>
      </div>
    </virtual-scroller>
  <div>
    <button (click)="onAddMoreItems()">Add more items</button>
  </div>
  `,
  styles: [
    `
  .grid-row {
    display: flex;
    flex-direction: row;
    width: 100%;
    gap: 1em;
  }

  .grid-row-id {
    width: 70px;
  }

  .grid-row-name {
    width: 150px;
  }

  .grid-row-email {
    width: 95px;
  }

  .grid-row-date {
    width: 190px;
  }

  virtual-scroller {
    width: 400px;
    height: 300px;
  }
  `,
  ],
})
export class App implements OnInit {
  items: IRow[] = [];

  ngOnInit(): void {
    this.items = this.createRows(50, 0);
  }

  onAddMoreItems(): void {
    const randomItemsCount = Math.round(10 + Math.random() * 10);
    this.items = [
      ...this.items,
      ...this.createRows(randomItemsCount, this.items.length),
    ];
  }

  onToggleRowExpansion(row: IRow): void {
    row.isExpanded = !row.isExpanded;
  }

  private createRows(count: number, startIndex: number): IRow[] {
    const rows: IRow[] = [];
    for (let i = 0; i < count; i++) {
      const id = startIndex + i;
      rows.push({
        id: '' + id,
        name: `Name ${id}`,
        date: `Date ${id}`,
        email: `Email ${id}`,
        isExpanded: false,
        expandedData: this.createRandomExpandedDateItems(i),
      });
    }
    return rows;
  }

  private createRandomExpandedDateItems(rowIndex: number): string[] {
    const expandedItemsCount = Math.round(5 + Math.random() * 5);
    const expandedItems: string[] = [];
    for (let j = 0; j < expandedItemsCount; j++) {
      expandedItems.push(`Row ${rowIndex} expanded item ${j}`);
    }
    return expandedItems;
  }
}

bootstrapApplication(App);

interface IRow {
  id: string;
  name: string;
  email: string;
  date: string;
  isExpanded: boolean;
  expandedData: string[];
}