0.2.3 • Published 7 years ago

angular-virtual-list v0.2.3

Weekly downloads
53
License
MIT
Repository
github
Last release
7 years ago

Angular Virtual List

This is a component to simulate virtual scroll for elements in Angular(v4) Forked from this project.

About

This module displays a small subset of records just enough to fill the viewport and uses the same DOM elements as the user scrolls. This method is effective because the number of DOM elements are always constant and tiny irrespective of the size of the list. Thus virtual scroll can display infinitely growing list of items in an efficient way.

  • Supports multi-column
  • Supports more than one million elements

Usage

<virtual-list [source$]="items$" (update)="viewPortItems = $event">

    <div *ngFor="let item of viewPortItems">{{item?.title}}</div>

</virtual-list>

Get Started

Step 1: Install angular-virtual-list

npm install angular-virtual-list --save

or

yarn add angular-virtual-list

Step 2: Import virtual list module into your app, or any module that consumes it.

import { VirtualListModule } from 'angular-virtual-list';

@NgModule({
    ...
    imports: [
        ....
        VirtualListModule,
    ],
})
export class AppModule { }

Step 3: Add your list item template;

<virtual-list [source$]="items$" (update)="viewPortItems = $event">

    <div *ngFor="let item of viewPortItems">{{item?.title}}</div>

</virtual-list>

API

AttributeTypeDescription
source$Observable<T[]>The source of data that builds the templates within the virtual list. This is the same data that you would pass to ngFor be ngFor will received splice of it. This input is an observable of an array containing your elements.
heightstringThe exact height of virtual list if you don't want the height of list to be calculated based on visible children you can set property. The value can be any valid metrics or you may set it to 'off' if you want to set the height of the list by styles, such as style="height: 300px".
childHeightnumberThe exact height of each child item. This is an optional input, virtual list will determine the height of elements automatically if this is not set. but this will have a bad result if they children's size are vary.
visibleChildrennumberDefault is 6. This set the visible items inside of view port.
bufferAmountnumberThe the number of elements to be rendered outside of the current container's viewport. Useful when not all elements are the same dimensions.
updateEventThis event is fired every time start or end index change and emits list of items from start to end. The list emitted by this event must be used with *ngFor to render the actual list of items within <virtual-list>
changeEventThis event is fired every time start or end index change and emits ChangeEvent which of format: { start: number, end: number }
scrollIntoMethodThis is a method to find and show one specific item from the source list into view port. This is the method signature scrollInto(item: T) => void.
refreshListMethodRefresh the current items in the view port.

Lazy Loading

The event end is fired every time scroll reaches at the end of the list. You could use this to load more items at the end of the scroll. See below.

import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { ChangeEvent } from 'angular-virtual-list';
...

@Component({
    selector: 'test-list',
    template: `
        <virtual-list
            [source$]="items$"
            (update)="scrollItems = $event"
            (end)="fetchMore($event)">

            <div *ngFor="let item of scrollItems">{{item?.title}}</div>
            <div *ngIf="loading" class="loader">Loading...</div>

        </virtual-list>
    `
})
export class ListWithApiComponent implements OnChanges {

    @Input()
    items: ListItem[];
    scrollList: ListItem[];

    protected items$ = new BehaviorSubject<ListItem[]>(null);
    protected buffer: ListItem[] = [];
    protected loading: boolean;

    protected fetchMore(event: ChangeEvent) {
        if (event.end !== this.buffer.length) return;
        this.loading = true;
        this.fetchNextChunk(this.buffer.length, 10).then(chunk => {
            this.buffer = this.buffer.concat(chunk);
            this.items$.next(this.buffer);
            this.loading = false;
        }, () => this.loading = false);
    }

    protected fetchNextChunk(skip: number, limit: number): Promise<ListItem[]> {
        return new Promise((resolve, reject) => {
            ....
        });
    }
}

Refresh current items

import { Component, ViewChild } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { VirtualListComponent } from 'angular-virtual-list';

@Component({
    selector: 'test-list',
    template: `
        <virtual-list [source$]="items$" (update)="scrollList = $event">
            <div *ngFor="let item of scrollList; let i = index"> {{i}}: {{item}} </div>
        </virtual-list>
    `
})
export class ListComponent {

    items = ['Item1', 'Item2', 'Item3'];
    scrollList = [];
    items$ = Observable.of(this.items);

    @ViewChild(VirtualListComponent)
    private virtualList: VirtualListComponent;

    // call this function after resize + animation end
    afterResize() {
        this.virtualList.refresh();
    }
}

Focus on an item

You could use scrollInto(item) api to scroll into an item in the list. See below:

import { Component, ViewChild } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { VirtualListComponent } from 'angular-virtual-list';

@Component({
    selector: 'test-list',
    template: `
        <virtual-list [source$]="items$" (update)="scrollList = $event">
            <div *ngFor="let item of scrollList; let i = index"> {{i}}: {{item}} </div>
        </virtual-list>
    `
})
export class ListComponent {

    items = ['Item1', 'Item2', 'Item3'];
    scrollList = [];
    items$ = Observable.of(this.items);

    @ViewChild(VirtualListComponent)
    private virtualList: VirtualListComponent;

    // call this function whenever you have to focus on second item
    focusOnAnItem() {
        this.virtualList.scrollInto(items[1]);
    }
}

Demo

Take a look at these example.

Credits

Initial developer: Rinto Jose