Skip to content

Commit

Permalink
Merge pull request #11 from lVlyke/0.1.0
Browse files Browse the repository at this point in the history
0.1.0
  • Loading branch information
lVlyke committed May 2, 2022
2 parents 23d0f6a + 4d1f743 commit 6977363
Show file tree
Hide file tree
Showing 15 changed files with 933 additions and 244 deletions.
212 changes: 203 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,225 @@
# @lithiumjs/ngx-virtual-scroll

A lightweight virtual scrolling solution for Angular that supports single column lists and grid lists. Built with [@lithiumjs/angular](https://github.com/lVlyke/lithium-angular).
A fast and lightweight virtual scrolling solution for Angular that supports single column lists, grid lists and view caching.

## [Live demo](https://lvlyke.github.io/lithium-ngx-virtual-scroll-demo/)

## How to use

@lithiumjs/ngx-virtual-scroll requires [@lithiumjs/angular](https://github.com/lVlyke/lithium-angular). Both can be installed from npm:

```bash
npm install @lithiumjs/angular @lithiumjs/ngx-virtual-scroll
```

Import the `NgxVirtualScrollModule`. Add the following to your component template:
Import `NgxVirtualScrollModule` into your application's module. Add the following to your component template:

```html
<!-- bufferLength is optional -->
<li-virtual-scroll [items]="items" [bufferLength]="3">
<li-virtual-scroll [items]="items">
<!-- liVirtualItem defines a list item element for each item -->
<div *liVirtualItem="let item">
{{ item.name }}
</div>
</li-virtual-scroll>
```

## Properties
### Grid lists (multiple items per row)

If the list being rendered is a grid list with multiple items per row, make sure to set `gridList` to `true`:

```html
<li-virtual-scroll [items]="items" [gridList]="true">
<div *liVirtualItem="let item">
{{ item.name }}
</div>
</li-virtual-scroll>
```

### Asynchronous view rendering

Asynchronous view rendering can be used to improve scrolling responsiveness for items with complex views. When enabled, a placeholder element will be temporarily be shown while the item is rendered asynchronously. The placeholder element can be customized using the `liVirtualPlaceholder` directive:

```html
<li-virtual-scroll [items]="items" [asyncRendering]="true">
<!-- Items contain complex components: -->
<div *liVirtualItem="let item">
{{ item.name }}

<app-complex-component></app-complex-component>
</div>

<!-- Placeholder only prints the item name: -->
<div *liVirtualPlaceholder="let item">
{{ item.name }}
</div>
</li-virtual-scroll>
```

Note that the placeholder should be lightweight so that it can be rendered quickly.

### View caching

View caching can be enabled to improve scrolling performance by caching views that are not being rendered for later re-use. View caching can be toggled on or off, or enabled with a maximum cache size (recommended for very large lists or complex views, as these could cause high memory usage):

```html
<!-- Up to 256 views will be cached -->
<li-virtual-scroll [items]="items" [viewCache]="256">
<div *liVirtualItem="let item">
{{ item.name }}
</div>
</li-virtual-scroll>
```

### Scroll debounce

The scroll debounce controls how often the virtual scroll should respond to scroll position changes. The default is 50 milliseconds.

```html
<!-- Virtual scroll will render on scroll changes every 100ms -->
<li-virtual-scroll [items]="items" [scrollDebounceMs]="100">
<div *liVirtualItem="let item">
{{ item.name }}
</div>
</li-virtual-scroll>
```

### Scroll buffer

Increasing the scroll buffer length will render more items outside of the viewport, which can reduce view pop-in when scrolling quickly. The buffer length is expressed in multiples of the list container's client height:

```html
<li-virtual-scroll [items]="items" [bufferLength]="3">
<div *liVirtualItem="let item">
{{ item.name }}
</div>
</li-virtual-scroll>
```

### Providing a custom virtual scroll strategy

The default virtual scroll strategy can be overriden by providing a custom `VirtualScrollStrategy` service implementation using the `LI_VIRTUAL_SCROLL_STRATEGY` injection token:

```ts
@NgModule({
providers: [
{
provide: LI_VIRTUAL_SCROLL_STRATEGY,
useClass: AppFooVirtualScrollStrategy
}
]
})
export class AppFooModule {}
```

The default virtual scroll strategy can also be overriden using `NgxVirtualScrollModule.withOptions`:

```ts
@NgModule({
imports: [
NgxVirtualScrollModule.withOptions({
scrollStrategy: AppFooVirtualScrollStrategy
})
]
})
export class AppModule {}
```

## API reference

### `VirtualScroll` (`li-virtual-scroll`)

Component used to create a virtual scrolling container.
#### **Inputs**

* **`items`** - The list of items to render.
* **`gridList`** - (Optional) Whether or not the list is a grid list with multiple items per row. Defaults to `false`.
* **`asyncRendering`** - (Optional) Whether or not to enable asynchronous rendering of views, which loads in placeholder elements while rendering items. Defaults to `false`.
* **`itemWidth`** - (Optional) The width of each item being rendered, in pixels. Calculated automatically if not given.
* **`itemHeight`** - (Optional) The height of each item being rendered, in pixels. Calculated automatically if not given.
* **`scrollDebounceMs`** - (Optional) How often to respond to scroll position changes, in milliseconds. Defaults to `50`.
* **`bufferLength`** - (Optional) How much extra list content should be rendered, measured in multiples of the list container's client height. This helps improve scrolling responsiveness for fast scrolling. Defaults to `1`.
* **`viewCache`** - (Optional) Whether views can be cached. Can be a boolean or a number representing the maximum number of views to cache at a given time. Defaults to `false`.
* **`scrollContainer`** - (Optional) The HTML element to use as the scroll container. Defaults to the host element.
* **`eventCapture`** - (Optional) Whether or not to use event capture mode for capturing scroll events from `scrollContainer`. Defaults to `false`.

### `VirtualItem` (`[liVirtualItem]`)

Structural directive used to render items inside a `li-virtual-scroll` component.

### `VirtualPlaceholder` (`[liVirtualPlaceholder]`)

Structural directive used to render placeholder elements inside a `li-virtual-scroll` component.

### `NgxVirtualScrollModule`

The Angular module for this library.
#### `NgxVirtualScrollModule.Options`

The options to configure the module with.

```ts
export interface Options {
scrollStrategy?: Type<VirtualScrollStrategy<unknown>>;
}
```

* `scrollStrategy` - The custom `VirtualScrollStrategy` service implementation to use.

#### `NgxVirtualScrollModule.withOptions`

Allows configuration of the module with custom options.

```ts
export class NgxVirtualScrollModule {

public static withOptions(
options: NgxVirtualScrollModule.Options
): ModuleWithProviders<NgxVirtualScrollModule>;
}
```

* `options` - The options to configure the module with.

### `VirtualScrollStrategy`

Interface for defining a custom virtual scroll strategy.

```ts
export interface VirtualScrollStrategy<T> {

destroyViewRef(
scrollState: VirtualScrollState<T>,
viewRef: EmbeddedViewRef<VirtualItem.ViewContext<T>>
): void;
destroyViewRefAt(
scrollState: VirtualScrollState<T>,
viewRef: EmbeddedViewRef<VirtualItem.ViewContext<T>>,
globalIndex: number
): void;
cacheViewRefAt(
scrollState: VirtualScrollState<T>,
viewRef: EmbeddedViewRef<VirtualItem.ViewContext<T>>,
globalIndex: number
): void;
renderViewForItemAt(
scrollState: VirtualScrollState<T>,
item: T,
globalIndex: number,
renderedViewIndices: number[],
deferViewCreation?: boolean
): Observable<EmbeddedViewRef<VirtualItem.ViewContext<T>>>;
unrenderViewRefAt(
scrollState: VirtualScrollState<T>,
viewRef: EmbeddedViewRef<VirtualItem.ViewContext<T>>,
globalIndex: number
): void;
purgeViewCache(scrollState: VirtualScrollState<T>): void;
}
```

### `DefaultVirtualScrollStrategy`

* **```items```** - The list of items to render.
* **```bufferLength```** - (Optional) How much extra list content should be rendered, measured in multiples of the list container's client height. This helps improve scrolling responsiveness for fast scrolling. Defaults to ```3```.
* **```scrollContainer```** - (Optional) The HTML entity to use as the scroll container. Defaults to the host element.
* **```eventCapture```** - (Optional) Whether or not to use event capture mode for capturing scroll events from ```scrollContainer```. Defaults to ```false```.
The default `VirtualScrollStrategy` service implementation.

## Other information

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"name": "@lithiumjs/ngx-virtual-scroll",
"description": "A fast virtual scrolling solution for Angular that natively supports items with unequal heights. Built with @lithiumjs/angular.",
"description": "A fast and lightweight virtual scrolling solution for Angular that supports single column lists, grid lists and view caching.",
"repository": "https://github.com/lVlyke/lithium-ngx-virtual-scroll",
"version": "0.0.6",
"version": "0.1.0",
"main": "index.js",
"author": "Mychal Thompson <[email protected]>",
"license": "MIT",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { InjectionToken } from "@angular/core";

export const LI_VIRTUAL_SCROLL_STATE = new InjectionToken("LI_VIRTUAL_SCROLL_STATE");
23 changes: 23 additions & 0 deletions src/components/virtual-scroll/scroll-state/virtual-scroll-state.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { EmbeddedViewRef, TemplateRef, ViewContainerRef } from "@angular/core";
import { VirtualItem } from "../../../directives/virtual-item.directive";
import { VirtualPlaceholder } from "../../../directives/virtual-placeholder.directive";

export interface VirtualScrollState<T> {

readonly items: T[];
readonly renderedItems: T[];
readonly viewCache: number | boolean;
readonly minIndex: number;
readonly maxIndex: number;

readonly virtualItem: VirtualItem<T>;
readonly viewContainerRef: ViewContainerRef;
readonly placeholderTemplate: TemplateRef<VirtualPlaceholder.ViewContext<T>>
readonly cachedViews: VirtualScrollState.ViewRecord<T>;
readonly renderedViews: VirtualScrollState.ViewRecord<T>;
}

export namespace VirtualScrollState {

export type ViewRecord<T> = Record<number, EmbeddedViewRef<VirtualItem.ViewContext<T>>>;
}
Loading

0 comments on commit 6977363

Please sign in to comment.