UNPKG

@rx-angular/template

Version:

**Fully** Reactive Component Template Rendering in Angular. @rx-angular/template aims to be a reflection of Angular's built in renderings just reactive.

1,135 lines (1,124 loc) 43.6 kB
import * as i0 from '@angular/core'; import { NgIterable, EmbeddedViewRef, ViewContainerRef, TrackByFunction, ElementRef, OnChanges, OnDestroy, SimpleChanges, OnInit, DoCheck, Signal, TemplateRef, InjectionToken, AfterViewInit, AfterContentInit } from '@angular/core'; import { RxDefaultListViewContext, RxListViewComputedContext } from '@rx-angular/cdk/template'; import * as rxjs from 'rxjs'; import { Observable, Subject } from 'rxjs'; import { RxStrategyNames } from '@rx-angular/cdk/render-strategies'; import * as _rx_angular_template_experimental_virtual_scrolling from '@rx-angular/template/experimental/virtual-scrolling'; interface ListRange { start: number; end: number; } /** * @Directive RxVirtualScrollStrategy * * @description * Abstract implementation for the actual implementations of the ScrollStrategies * being consumed by `*rxVirtualFor` and `rx-virtual-scroll-viewport`. * * This is one of the core parts for the virtual scrolling implementation. It has * to determine the `ListRange` being rendered to the DOM as well as managing * the layouting task for the `*rxVirtualFor` directive. * * @docsCategory RxVirtualFor * @docsPage RxVirtualFor * @publicApi */ declare abstract class RxVirtualScrollStrategy<T, U extends NgIterable<T> = NgIterable<T>> { /** Emits when the index of the first element visible in the viewport changes. */ /** @internal */ abstract scrolledIndex$: Observable<number>; /** @internal */ abstract renderedRange$: Observable<ListRange>; /** @internal */ abstract contentSize$: Observable<number>; /** @internal */ get isStable(): Observable<boolean>; /** * @description * * Emits whenever an update to a single view was rendered */ readonly viewRenderCallback: Subject<{ view: EmbeddedViewRef<RxVirtualForViewContext<T, U>>; item: T; index: number; }>; /** @internal */ private nodeIndex?; /** @internal */ protected getElement(view: EmbeddedViewRef<RxVirtualForViewContext<T, U>>): HTMLElement; /** * Attaches this scroll strategy to a viewport. * @param viewport The viewport to attach this strategy to. * @param viewRepeater The viewRepeater attached to the viewport. */ abstract attach(viewport: RxVirtualScrollViewport, viewRepeater: RxVirtualViewRepeater<any>): void; /** Detaches this scroll strategy from the currently attached viewport. */ abstract detach(): void; /** * Scroll to the offset for the given index. * @param index The index of the element to scroll to. * @param behavior The ScrollBehavior to use when scrolling. */ abstract scrollToIndex(index: number, behavior?: ScrollBehavior): void; static ɵfac: i0.ɵɵFactoryDeclaration<RxVirtualScrollStrategy<any, any>, never>; static ɵdir: i0.ɵɵDirectiveDeclaration<RxVirtualScrollStrategy<any, any>, never, never, {}, {}, never, never, true, never>; } /** @internal */ declare abstract class RxVirtualScrollViewport { abstract elementScrolled$: Observable<void>; abstract containerRect$: Observable<{ height: number; width: number; }>; abstract getScrollTop(): number; abstract scrollTo(scrollTo: number, behavior?: ScrollBehavior): void; abstract getScrollElement(): HTMLElement; abstract measureOffset(): number; static ɵfac: i0.ɵɵFactoryDeclaration<RxVirtualScrollViewport, never>; static ɵdir: i0.ɵɵDirectiveDeclaration<RxVirtualScrollViewport, never, never, {}, {}, never, never, true, never>; } /** @internal */ declare abstract class RxVirtualViewRepeater<T, U extends NgIterable<T> = NgIterable<T>> { abstract values$: Observable<U | null | undefined>; abstract viewsRendered$: Observable<EmbeddedViewRef<RxVirtualForViewContext<T, U>>[]>; abstract viewRendered$: Observable<{ view: EmbeddedViewRef<RxVirtualForViewContext<T, U>>; index: number; item: T; }>; abstract viewContainer: ViewContainerRef; abstract renderingStart$: Observable<Set<number>>; _trackBy: TrackByFunction<T> | null; static ɵfac: i0.ɵɵFactoryDeclaration<RxVirtualViewRepeater<any, any>, never>; static ɵdir: i0.ɵɵDirectiveDeclaration<RxVirtualViewRepeater<any, any>, never, never, {}, {}, never, never, true, never>; } /** @internal */ declare class RxVirtualForViewContext<T, U extends NgIterable<T> = NgIterable<T>, C extends { count: number; index: number; } = { count: number; index: number; }, K = keyof T> extends RxDefaultListViewContext<T, U, K> { rxVirtualForOf: U; constructor(item: T, rxVirtualForOf: U, customProps?: C); } declare abstract class RxVirtualScrollElement { abstract elementScrolled$: Observable<void>; abstract getElementRef(): ElementRef<HTMLElement>; abstract measureOffset(): number; static ɵfac: i0.ɵɵFactoryDeclaration<RxVirtualScrollElement, never>; static ɵdir: i0.ɵɵDirectiveDeclaration<RxVirtualScrollElement, never, never, {}, {}, never, never, true, never>; } /** * @Directive AutosizeVirtualScrollStrategy * * @description * * The `AutosizeVirtualScrollStrategy` provides a twitter-like virtual-scrolling * experience. It is able to render and position items based on their individual * size. It is comparable to \@angular/cdk/experimental `AutosizeVirtualScrollStrategy`, but * with a high performant layouting technique and more features. * * On top of this the `AutosizeVirtualScrollStrategy` is leveraging the native * `ResizeObserver` in order to detect size changes for each individual view * rendered to the DOM and properly re-position accordingly. * * In order to provide top-notch runtime performance the `AutosizeVirtualScrollStrategy` * builds up caches that prevent DOM interactions whenever possible. Once a view * was visited, its properties will be stored instead of re-read from the DOM again as * this can potentially lead to unwanted forced reflows. * * @docsCategory RxVirtualFor * @docsPage RxVirtualFor * @publicApi */ declare class AutoSizeVirtualScrollStrategy<T, U extends NgIterable<T> = NgIterable<T>> extends RxVirtualScrollStrategy<T, U> implements OnChanges, OnDestroy { private readonly defaults?; /** * @description * The amount of items to render upfront in scroll direction */ runwayItems: number; /** * @description * The amount of items to render upfront in reverse scroll direction */ runwayItemsOpposite: number; /** * @description * The default size of the items being rendered. The autosized strategy will assume * this size for items it doesn't know yet. For the smoothest experience, * you provide the mean size of all items being rendered - if possible of course. * * As soon as rxVirtualFor is able to also render actual tombstone items, this * will be the size of a tombstone item being rendered before the actual item * is inserted into its position. */ tombstoneSize: number; /** * @description * The autosized strategy uses the native ResizeObserver in order to determine * if an item changed in size to afterwards properly position the views. * You can customize the config passed to the ResizeObserver as well as determine * which result property to use when determining the views size. */ resizeObserverConfig?: { options?: ResizeObserverOptions; extractSize?: (entry: ResizeObserverEntry) => number; }; /** * @description * When enabled, the autosized scroll strategy attaches a `ResizeObserver` * to every view within the given renderedRange. If your views receive * dimension changes that are not caused by list updates, this is a way to * still track height changes. This also applies to resize events of the whole * document. */ withResizeObserver: boolean; /** * @description * When enabled, the scroll strategy stops removing views from the viewport, * instead it only adds views. This setting can be changed on the fly. Views will be added in both directions * according to the user interactions. */ appendOnly: boolean; /** * @description * When enabled, the autosized scroll strategy removes css styles that * prevent the scrollbar from being in sync with the input device. * Use with caution, as this can lead to extremely weird scroll behavior * on chromium based browsers when the rendered views differ * in dimensions too much or change dimensions heavily. */ withSyncScrollbar: boolean; /** * @description * If this flag is true, the virtual scroll strategy maintains the scrolled item when new data * is prepended to the list. This is very useful when implementing a reversed infinite scroller, that prepends * data instead of appending it */ keepScrolledIndexOnPrepend: boolean; /** @internal */ private viewport; /** @internal */ private viewRepeater; /** @internal */ private readonly _contentSize$; /** @internal */ readonly contentSize$: Observable<number>; /** @internal */ private _contentSize; /** @internal */ private set contentSize(value); private get contentSize(); /** @internal */ private readonly _renderedRange$; /** @internal */ readonly renderedRange$: Observable<ListRange>; /** @internal */ private _renderedRange; /** @internal */ private set renderedRange(value); /** @internal */ private get renderedRange(); /** @internal */ private positionedRange; /** @internal */ private readonly _scrolledIndex$; /** @internal */ readonly scrolledIndex$: Observable<number>; /** * @internal * The action used to kick off the scroll process */ private scrollToTrigger$; /** @internal */ private _scrolledIndex; /** @internal */ private get scrolledIndex(); /** @internal */ private set scrolledIndex(value); /** * is set, when scrollToIndex is called * @internal * */ private _scrollToIndex; /** @internal */ private containerSize; /** @internal */ private contentLength; /** @internal */ private _virtualItems; /** @internal */ private scrollTop; /** @internal */ private scrollTopWithOutOffset; /** @internal */ private scrollTopAfterOffset; /** @internal */ private viewportOffset; /** @internal */ private direction; /** @internal */ private anchorScrollTop; /** @internal */ private anchorItem; /** @internal */ private lastScreenItem; /** @internal */ private waitForScroll; /** @internal */ private isStable$; /** @internal */ private readonly detached$; /** @internal */ private resizeObserver; /** @internal */ private readonly recalculateRange$; /** @internal */ private until$; /** @internal */ private get extractSize(); /** @internal */ get isStable(): Observable<boolean>; /** @internal */ ngOnChanges(changes: SimpleChanges): void; /** @internal */ ngOnDestroy(): void; /** @internal */ attach(viewport: RxVirtualScrollViewport, viewRepeater: RxVirtualViewRepeater<T, U>): void; /** @internal */ detach(): void; scrollToIndex(index: number, behavior?: ScrollBehavior): void; private scrollTo; /** * starts the subscriptions that maintain the virtualItems array on changes * to the underlying dataset * @internal */ private maintainVirtualItems; /** * listen to triggers that should change the renderedRange * @internal */ private calcRenderedRange; /** * position elements after they are created/updated/moved or their dimensions * change from other sources * @internal */ private positionElements; /** listen to API initiated scroll triggers (e.g. initialScrollIndex) */ private listenToScrollTrigger; /** @internal */ private adjustContentSize; /** @internal */ private observeViewSize$; /** * @internal * heavily inspired by * https://github.com/GoogleChromeLabs/ui-element-samples/blob/gh-pages/infinite-scroller/scripts/infinite-scroll.js */ private calculateAnchoredItem; /** @internal */ private positionUnchangedViews; /** * Adjust the scroll position when the anchorScrollTop differs from * the actual scrollTop. * Trigger a range recalculation if there is empty space * * @internal */ private maybeAdjustScrollPosition; /** @internal */ private calcAnchorScrollTop; /** @internal */ private calcInitialPosition; /** @internal */ private getViewRef; /** @internal */ private updateElementSize; /** @internal */ private getItemSize; /** @internal */ private getElementSize; /** @internal */ private positionElement; /** @internal */ private updateScrollElementClass; static ɵfac: i0.ɵɵFactoryDeclaration<AutoSizeVirtualScrollStrategy<any, any>, never>; static ɵdir: i0.ɵɵDirectiveDeclaration<AutoSizeVirtualScrollStrategy<any, any>, "rx-virtual-scroll-viewport[autosize]", never, { "runwayItems": { "alias": "runwayItems"; "required": false; }; "runwayItemsOpposite": { "alias": "runwayItemsOpposite"; "required": false; }; "tombstoneSize": { "alias": "tombstoneSize"; "required": false; }; "resizeObserverConfig": { "alias": "resizeObserverConfig"; "required": false; }; "withResizeObserver": { "alias": "withResizeObserver"; "required": false; }; "appendOnly": { "alias": "appendOnly"; "required": false; }; "withSyncScrollbar": { "alias": "withSyncScrollbar"; "required": false; }; "keepScrolledIndexOnPrepend": { "alias": "keepScrolledIndexOnPrepend"; "required": false; }; }, {}, never, never, true, never>; static ngAcceptInputType_withResizeObserver: null | boolean | string | undefined; static ngAcceptInputType_appendOnly: null | boolean | string | undefined; static ngAcceptInputType_withSyncScrollbar: null | boolean | string | undefined; static ngAcceptInputType_keepScrolledIndexOnPrepend: null | boolean | string | undefined; } /** * @Directive DynamicSizeVirtualScrollStrategy * * @description * * The `DynamicSizeVirtualScrollStrategy` is very similar to the `AutosizeVirtualScrollStrategy`. * It positions items based on a function determining its size. * * @docsCategory RxVirtualFor * @docsPage RxVirtualFor * @publicApi */ declare class DynamicSizeVirtualScrollStrategy<T, U extends NgIterable<T> = NgIterable<T>> extends RxVirtualScrollStrategy<T, U> implements OnChanges, OnDestroy { private readonly defaults?; /** * @description * The amount of items to render upfront in scroll direction */ runwayItems: number; /** * @description * The amount of items to render upfront in reverse scroll direction */ runwayItemsOpposite: number; /** * @description * When enabled, the scroll strategy stops removing views from the viewport, * instead it only adds views. This setting can be changed on the fly. Views will be added in both directions * according to the user interactions. */ appendOnly: boolean; /** * @description * If this flag is true, the virtual scroll strategy maintains the scrolled item when new data * is prepended to the list. This is very useful when implementing a reversed infinite scroller, that prepends * data instead of appending it */ keepScrolledIndexOnPrepend: boolean; /** * @description * Function returning the size of an item */ set itemSize(fn: (item: T) => number); get itemSize(): (item: T) => number; private _itemSizeFn; /** @internal */ private waitForScroll; /** @internal */ private isStable$; /** @internal */ get isStable(): Observable<boolean>; /** @internal */ private viewport; /** @internal */ private viewRepeater; /** @internal */ private readonly _contentSize$; /** @internal */ readonly contentSize$: Observable<number>; /** @internal */ private _contentSize; /** @internal */ private set contentSize(value); private get contentSize(); /** @internal */ private readonly _renderedRange$; /** @internal */ readonly renderedRange$: Observable<ListRange>; /** @internal */ private _renderedRange; /** @internal */ private set renderedRange(value); /** @internal */ private get renderedRange(); /** @internal */ private readonly _scrolledIndex$; /** @internal */ readonly scrolledIndex$: Observable<number>; private _scrolledIndex; /** @internal */ private set scrolledIndex(value); private get scrolledIndex(); /** @internal */ private get contentLength(); /** @internal */ private containerSize; /** @internal */ private _virtualItems; /** @internal */ private scrollTop; /** @internal */ private scrollTopWithOutOffset; /** @internal */ private scrollTopAfterOffset; /** @internal */ private viewportOffset; /** @internal */ private direction; /** @internal */ private anchorScrollTop; /** @internal */ private anchorItem; /** @internal */ private lastScreenItem; /** @internal */ private readonly detached$; /** @internal */ private readonly recalculateRange$; /** @internal */ private until$; /** @internal */ ngOnChanges(changes: SimpleChanges): void; /** @internal */ ngOnDestroy(): void; /** @internal */ attach(viewport: RxVirtualScrollViewport, viewRepeater: RxVirtualViewRepeater<T, U>): void; /** @internal */ detach(): void; scrollToIndex(index: number, behavior?: ScrollBehavior): void; private scrollTo; /** @internal */ private maintainVirtualItems; /** @internal */ private calcRenderedRange; /** @internal */ private positionElements; /** * @internal * heavily inspired by * https://github.com/GoogleChromeLabs/ui-element-samples/blob/gh-pages/infinite-scroller/scripts/infinite-scroll.js */ private calculateAnchoredItem; /** @internal */ private calcInitialPosition; /** @internal */ private calcAnchorScrollTop; /** @internal */ private getItemSize; /** @internal */ private positionElement; static ɵfac: i0.ɵɵFactoryDeclaration<DynamicSizeVirtualScrollStrategy<any, any>, never>; static ɵdir: i0.ɵɵDirectiveDeclaration<DynamicSizeVirtualScrollStrategy<any, any>, "rx-virtual-scroll-viewport[dynamic]", never, { "runwayItems": { "alias": "runwayItems"; "required": false; }; "runwayItemsOpposite": { "alias": "runwayItemsOpposite"; "required": false; }; "appendOnly": { "alias": "appendOnly"; "required": false; }; "keepScrolledIndexOnPrepend": { "alias": "keepScrolledIndexOnPrepend"; "required": false; }; "itemSize": { "alias": "dynamic"; "required": false; }; }, {}, never, never, true, never>; static ngAcceptInputType_appendOnly: null | boolean | string | undefined; static ngAcceptInputType_keepScrolledIndexOnPrepend: null | boolean | string | undefined; } /** * @Directive FixedSizeVirtualScrollStrategy * * @description * * The `FixedSizeVirtualScrollStrategy` provides a very performant way of rendering * items of a given size. It is comparable to \@angular/cdk `FixedSizeVirtualScrollStrategy`, but * with a high performant layouting technique. * * @docsCategory RxVirtualFor * @docsPage RxVirtualFor * @publicApi */ declare class FixedSizeVirtualScrollStrategy<T, U extends NgIterable<T> = NgIterable<T>> extends RxVirtualScrollStrategy<T, U> implements OnChanges, OnDestroy { private readonly defaults?; /** * @description * The size of the items in the virtually scrolled list */ set itemSize(itemSize: number); get itemSize(): number; private _itemSize; /** * @description * When enabled, the scroll strategy stops removing views from the viewport, * instead it only adds views. This setting can be changed on the fly. Views will be added in both directions * according to the user interactions. */ appendOnly: boolean; /** * @description * The amount of items to render upfront in scroll direction */ runwayItems: number; /** * @description * The amount of items to render upfront in reverse scroll direction */ runwayItemsOpposite: number; /** * @description * If this flag is true, the virtual scroll strategy maintains the scrolled item when new data * is prepended to the list. This is very useful when implementing a reversed infinite scroller, that prepends * data instead of appending it */ keepScrolledIndexOnPrepend: boolean; /** @internal */ private readonly runwayStateChanged$; private viewport; private viewRepeater; private readonly _scrolledIndex$; readonly scrolledIndex$: rxjs.Observable<number>; private _scrolledIndex; private set scrolledIndex(value); private get scrolledIndex(); private readonly _contentSize$; readonly contentSize$: rxjs.Observable<number>; private _contentSize; private set contentSize(value); private readonly _renderedRange$; renderedRange$: rxjs.Observable<ListRange>; private _renderedRange; private set renderedRange(value); private get renderedRange(); private scrollTop; /** @internal */ private scrollTopWithOutOffset; /** @internal */ private scrollTopAfterOffset; /** @internal */ private viewportOffset; /** @internal */ private containerSize; private direction; private readonly detached$; /** @internal */ ngOnChanges(changes: SimpleChanges): void; ngOnDestroy(): void; attach(viewport: RxVirtualScrollViewport, viewRepeater: RxVirtualViewRepeater<T, U>): void; detach(): void; private positionElements; private calcRenderedRange; scrollToIndex(index: number, behavior?: ScrollBehavior): void; private untilDetached$; private _setViewPosition; static ɵfac: i0.ɵɵFactoryDeclaration<FixedSizeVirtualScrollStrategy<any, any>, never>; static ɵdir: i0.ɵɵDirectiveDeclaration<FixedSizeVirtualScrollStrategy<any, any>, "rx-virtual-scroll-viewport[itemSize]", never, { "itemSize": { "alias": "itemSize"; "required": false; }; "appendOnly": { "alias": "appendOnly"; "required": false; }; "runwayItems": { "alias": "runwayItems"; "required": false; }; "runwayItemsOpposite": { "alias": "runwayItemsOpposite"; "required": false; }; "keepScrolledIndexOnPrepend": { "alias": "keepScrolledIndexOnPrepend"; "required": false; }; }, {}, never, never, true, never>; static ngAcceptInputType_appendOnly: null | boolean | string | undefined; static ngAcceptInputType_keepScrolledIndexOnPrepend: null | boolean | string | undefined; } /** * @Directive RxVirtualFor * * @description * * The `*rxVirtualFor` structural directive provides a convenient and performant * way for rendering huge lists of items. It brings all the benefits `rxFor` does, * and implements virtual rendering. * * Instead of rendering every item provided, rxVirtualFor only renders what is * currently visible to the user, thus providing excellent runtime performance * for huge sets of data. * * The technique to render items is comparable to the on used by twitter and * explained in very much detail by @DasSurma in his blog post about the [complexities * of infinite scrollers](https://developer.chrome.com/blog/infinite-scroller/). * * "Each recycling of a DOM element would normally relayout the entire runway which * would bring us well below our target of 60 frames per second. * To avoid this, we are taking the burden of layout onto ourselves and use * absolutely positioned elements with transforms." (@DasSurma) * * ## API * The API is a combination of \@rx-angular/template/for & * \@angular/cdk `*cdkVirtualFor`. * * trackBy: `(index: number, item: T) => any` | `keyof T` * * strategy: `string` | `Observable<string>` * * parent: `boolean`; * * renderCallback: `Subject<T[]>` * * viewCache: `number` * * (Injected) scrollStrategy: `RxVirtualScrollStrategy<T, U>` * * provides itself as RxVirtualViewRepeater for RxVirtualViewPortComponent to operate * * ## Features * * Push based architecture * * Comprehensive set of context variables * * Opt-out of `NgZone` with `patchZone` * * Notify when rendering of child templates is finished (`renderCallback`) * * Super efficient layouting with css transformations * * Define a viewCache in order to re-use views instead of re-creating them * * Configurable RxVirtualScrollStrategy<T, U> providing the core logic to calculate the viewRange and position DOM * Nodes * * ### Context Variables * * The following context variables are available for each template: * * - $implicit: `T` // the default variable accessed by `let val` * - item$: `Observable<T>` // the same value as $implicit, but as `Observable` * - index: `number` // current index of the item * - count: `number` // count of all items in the list * - first: `boolean` // true if the item is the first in the list * - last: `boolean` // true if the item is the last in the list * - even: `boolean` // true if the item has on even index (index % 2 === 0) * - odd: `boolean` // the opposite of even * - index$: `Observable<number>` // index as `Observable` * - count$: `Observable<number>` // count as `Observable` * - first$: `Observable<boolean>` // first as `Observable` * - last$: `Observable<boolean>` // last as `Observable` * - even$: `Observable<boolean>` // even as `Observable` * - odd$: `Observable<boolean>` // odd as `Observable` * - select: `(keys: (keyof T)[], distinctByMap) => Observable<Partial<T>>` * // returns a selection function which * // accepts an array of properties to pluck out of every list item. The function returns the selected properties of * // the current list item as distinct `Observable` key-value-pair. See the example below: * * This example showcases the `select` view-context function used for deeply nested lists. * * ```html * <rx-virtual-scroll-viewport> * <div * autosized * *rxVirtualFor="let hero of heroes$; trackBy: trackItem; let select = select;"> * <div> * <strong>{{ hero.name }}</strong></br> * Defeated enemies: * </div> * <span *rxFor="let enemy of select(['defeatedEnemies']); trackBy: trackEnemy;"> * {{ enemy.name }} * </span> * </div> * </rx-virtual-scroll-viewport> * ``` * * ### Using the context variables * * ```html * <rx-virtual-scroll-viewport> * <div * *rxVirtualFor=" * let item of observableItems$; * let count = count; * let index = index; * let first = first; * let last = last; * let even = even; * let odd = odd; * trackBy: trackItem; * " * > * <div>{{ count }}</div> * <div>{{ index }}</div> * <div>{{ item }}</div> * <div>{{ first }}</div> * <div>{{ last }}</div> * <div>{{ even }}</div> * <div>{{ odd }}</div> * </div> * </rx-virtual-scroll-viewport> * ``` * * @docsCategory RxVirtualFor * @docsPage RxVirtualFor * @publicApi */ declare class RxVirtualFor<T, U extends NgIterable<T> = NgIterable<T>> implements RxVirtualViewRepeater<T>, OnInit, DoCheck, OnDestroy { private readonly templateRef; private readonly scrollStrategy; private readonly iterableDiffers; private readonly cdRef; private readonly ngZone; /** @internal */ private injector; readonly viewContainer: ViewContainerRef; private readonly strategyProvider; private readonly errorHandler; private readonly defaults?; /** @internal */ private _differ?; /** @internal */ private partiallyFinished; /** @internal */ private staticValue?; /** @internal */ private renderStatic; /** * @description * The iterable input * * @example * <rx-virtual-scroll-viewport> * <app-hero *rxVirtualFor="heroes$; let hero" * [hero]="hero"></app-hero> * </rx-virtual-scroll-viewport> * * @param potentialSignalOrObservable */ set rxVirtualForOf(potentialSignalOrObservable: Observable<(U & NgIterable<T>) | undefined | null> | Signal<(U & NgIterable<T>) | undefined | null> | (U & NgIterable<T>) | null | undefined); /** * @internal * A reference to the template that is created for each item in the iterable. * @see [template reference variable](guide/template-reference-variables) * (inspired by @angular/common `ng_for_of.ts`) */ private _template?; set rxVirtualForTemplate(value: TemplateRef<RxVirtualForViewContext<T, U>>); /** @internal */ private strategyHandler; /** * @description * The rendering strategy to be used to render updates to the DOM. * Use it to dynamically manage your rendering strategy. You can switch the strategy * imperatively (with a string) or by binding an Observable. * The default strategy is `'normal'` if not configured otherwise. * * @example * \@Component({ * selector: 'app-root', * template: ` * <rx-virtual-scroll-viewport> * <app-hero * autosized * *rxVirtualFor="let hero of heroes$; strategy: strategy" * [hero]="hero"></app-hero> * </rx-virtual-scroll-viewport> * ` * }) * export class AppComponent { * strategy = 'low'; * } * * // OR * * \@Component({ * selector: 'app-root', * template: ` * <rx-virtual-scroll-viewport> * <app-hero * autosized * *rxVirtualFor="let hero of heroes$; strategy: strategy$" * [hero]="hero"></app-hero> * </rx-virtual-scroll-viewport> * ` * }) * export class AppComponent { * strategy$ = new BehaviorSubject('immediate'); * } * * @param strategyName * @see {@link strategies} */ set strategy(strategyName: RxStrategyNames<string> | Observable<RxStrategyNames<string>>); /** * @description * Controls the amount if views held in cache for later re-use when a user is * scrolling the list. If this is set to 0, `rxVirtualFor` won't cache any view, * thus destroying & re-creating very often on scroll events. */ templateCacheSize: number; /** * @description * If `parent` is set to `true` (default to `false`), `*rxVirtualFor` will * automatically run change-detection for its parent component when its scheduled * tasks are done in order to update any pending `@ContentChild` or `@ViewChild` * relation to be updated according to the updated ViewContainer. * * @example * \@Component({ * selector: 'app-root', * template: ` * <rx-virtual-scroll-viewport> * <app-list-item * *rxVirtualFor=" * let item of items$; * trackBy: trackItem; * parent: true; * " * [item]="item" * autosized * ></app-list-item> * </rx-virtual-scroll-viewport> * ` * }) * export class AppComponent { * // those queries won't be in sync with what `rxVirtualFor` is rendering * // when parent is set to false. * \@ViewChildren(AppListItem) listItems: QueryList<AppListItem>; * * items$ = itemService.getItems(); * } * * @param renderParent * * @deprecated this flag will be dropped soon, as it is no longer required when using signal based view & content queries */ renderParent: boolean; /** * @description * A flag to control whether `*rxVirtualFor` rendering happens within * `NgZone` or not. The default value is set to `true` if not configured otherwise. * If `patchZone` is set to `false` `*rxVirtualFor` will operate completely outside of `NgZone`. * * @example * \@Component({ * selector: 'app-root', * template: ` * <rx-virtual-scroll-viewport> * <app-list-item * *rxVirtualFor=" * let item of items$; * trackBy: trackItem; * patchZone: false; * " * [item]="item" * autosized * ></app-list-item> * </rx-virtual-scroll-viewport> * ` * }) * export class AppComponent { * items$ = itemService.getItems(); * } * * @param patchZone */ patchZone: boolean; /** * @description * A function or key that defines how to track changes for items in the provided * iterable data. * * When items are added, moved, or removed in the iterable, * the directive must re-render the appropriate DOM nodes. * To minimize operations on the DOM, only nodes that have changed * are re-rendered. * * By default, `rxVirtualFor` assumes that the object instance identifies * the node in the iterable (equality check `===`). * When a function or key is supplied, `rxVirtualFor` uses the result to identify the item node. * * @example * \@Component({ * selector: 'app-root', * template: ` * <rx-virtual-scroll-viewport> * <app-list-item * *rxVirtualFor=" * let item of items$; * trackBy: 'id'; * " * autosized * [item]="item" * > * </app-list-item> * </rx-virtual-scroll-viewport> * ` * }) * export class AppComponent { * items$ = itemService.getItems(); * } * * // OR * * \@Component({ * selector: 'app-root', * template: ` * <rx-virtual-scroll-viewport> * <app-list-item * *rxVirtualFor=" * let item of items$; * trackBy: trackItem; * " * autosized * [item]="item" * > * </app-list-item> * </rx-virtual-scroll-viewport> * ` * }) * export class AppComponent { * items$ = itemService.getItems(); * trackItem = (idx, item) => item.id; * } * * @param trackByFnOrKey */ set trackBy(trackByFnOrKey: keyof T | TrackByFunction<T>); /** * @description * A `Subject` which emits whenever `*rxVirtualFor` finished rendering a * set of changes to the view. * This enables developers to perform actions exactly at the timing when the * updates passed are rendered to the DOM. * The `renderCallback` is useful in situations where you rely on specific DOM * properties like the `height` of a table after all items got rendered. * It is also possible to use the renderCallback in order to determine if a * view should be visible or not. This way developers can hide a list as * long as it has not finished rendering. * * The result of the `renderCallback` will contain the currently rendered set * of items in the iterable. * * @example * \@Component({ * selector: 'app-root', * template: ` * <rx-virtual-scroll-viewport> * <app-list-item * *rxVirtualFor=" * let item of items$; * trackBy: trackItem; * renderCallback: itemsRendered; * " * autosized * [item]="item" * > * </app-list-item> * </rx-virtual-scroll-viewport> * ` * }) * export class AppComponent { * items$: Observable<Item[]> = itemService.getItems(); * trackItem = (idx, item) => item.id; * // this emits whenever rxVirtualFor finished rendering changes * itemsRendered = new Subject<Item[]>(); * } * * @param renderCallback */ set renderCallback(renderCallback: Subject<U>); /** @internal */ readonly viewsRendered$: Subject<EmbeddedViewRef<RxVirtualForViewContext<T, U, RxListViewComputedContext, keyof T>>[]>; /** @internal */ readonly viewRendered$: Subject<{ view: EmbeddedViewRef<RxVirtualForViewContext<T, U>>; index: number; item: T; }>; /** @internal */ readonly renderingStart$: Subject<Set<number>>; /** @internal */ private get template(); /** @internal */ private observables$; /** @internal */ private _renderCallback?; /** @internal */ readonly values$: Observable<NgIterable<T>>; /** @internal */ private values?; /** @internal */ private templateManager; /** @internal */ private _destroy$; /** @internal */ _trackBy: TrackByFunction<T> | null; /** @internal */ static ngTemplateContextGuard<T, U extends NgIterable<T> = NgIterable<T>, K = keyof T>(dir: RxVirtualFor<T, U>, ctx: any): ctx is RxVirtualForViewContext<T, U, RxListViewComputedContext, K>; constructor(templateRef: TemplateRef<RxVirtualForViewContext<T, U>>); /** @internal */ ngOnInit(): void; /** @internal */ ngDoCheck(): void; /** @internal */ ngOnDestroy(): void; private render; private handleError; private getDiffer; /** @internal */ private createViewContext; /** @internal */ private updateViewContext; static ɵfac: i0.ɵɵFactoryDeclaration<RxVirtualFor<any, any>, never>; static ɵdir: i0.ɵɵDirectiveDeclaration<RxVirtualFor<any, any>, "[rxVirtualFor][rxVirtualForOf]", never, { "rxVirtualForOf": { "alias": "rxVirtualForOf"; "required": false; }; "rxVirtualForTemplate": { "alias": "rxVirtualForTemplate"; "required": false; }; "strategy": { "alias": "rxVirtualForStrategy"; "required": false; }; "templateCacheSize": { "alias": "rxVirtualForTemplateCacheSize"; "required": false; }; "renderParent": { "alias": "rxVirtualForParent"; "required": false; }; "patchZone": { "alias": "rxVirtualForPatchZone"; "required": false; }; "trackBy": { "alias": "rxVirtualForTrackBy"; "required": false; }; "renderCallback": { "alias": "rxVirtualForRenderCallback"; "required": false; }; }, {}, never, never, true, never>; } interface RxVirtualScrollDefaultOptions { templateCacheSize?: number; runwayItems?: number; runwayItemsOpposite?: number; itemSize?: number; } /** Injection token to be used to override the default options. */ declare const RX_VIRTUAL_SCROLL_DEFAULT_OPTIONS: InjectionToken<RxVirtualScrollDefaultOptions>; /** @internal */ declare function RX_VIRTUAL_SCROLL_DEFAULT_OPTIONS_FACTORY(): RxVirtualScrollDefaultOptions; declare class RxVirtualScrollElementDirective implements RxVirtualScrollElement { private readonly elementRef; readonly elementScrolled$: rxjs.Observable<void>; getElementRef(): ElementRef<HTMLElement>; measureOffset(): number; static ɵfac: i0.ɵɵFactoryDeclaration<RxVirtualScrollElementDirective, never>; static ɵdir: i0.ɵɵDirectiveDeclaration<RxVirtualScrollElementDirective, "[rxVirtualScrollElement]", never, {}, {}, never, never, true, never>; } /** * @Component RxVirtualScrollViewport * * @description * Container component comparable to CdkVirtualScrollViewport acting as viewport * for `*rxVirtualFor` to operate on. * * Its main purpose is to implement the `RxVirtualScrollViewport` interface * as well as maintaining the scroll runways' height in order to give * the provided `RxVirtualScrollStrategy` room to position items. * * Furthermore, it will gather and forward all events to the consumer of `rxVirtualFor`. * * @docsCategory RxVirtualFor * @docsPage RxVirtualFor * @publicApi */ declare class RxVirtualScrollViewportComponent implements RxVirtualScrollViewport, AfterViewInit, AfterContentInit, OnDestroy { private elementRef; private scrollStrategy; protected scrollElement: RxVirtualScrollElement; /** * @description * * Sets the first view to be visible to the user. * The viewport waits for the data to arrive and scrolls to the given index immediately. * * */ initialScrollIndex: number; /** @internal */ private scrollSentinel; /** @internal */ private runway; /** @internal */ viewRepeater: RxVirtualViewRepeater<unknown>; readonly elementScrolled$: rxjs.Observable<void>; /** @internal */ private _containerRect$; readonly containerRect$: rxjs.Observable<{ width: number; height: number; }>; /** * @description * * The range to be rendered by `*rxVirtualFor`. This value is determined by the * provided `RxVirtualScrollStrategy`. It gives the user information about the * range of items being actually rendered to the DOM. * Note this value updates before the `renderCallback` kicks in, thus it is only * in sync with the DOM when the next `renderCallback` emitted an event. */ readonly viewRange: rxjs.Observable<_rx_angular_template_experimental_virtual_scrolling.ListRange>; /** * @description * * The index of the currently scrolled item. The scrolled item is the topmost * item actually being visible to the user. */ readonly scrolledIndexChange: rxjs.Observable<number>; /** @internal */ private readonly destroy$; /** @internal */ constructor(); ngAfterViewInit(): void; /** @internal */ ngAfterContentInit(): void; /** @internal */ ngOnDestroy(): void; getScrollElement(): HTMLElement; getScrollTop(): number; scrollTo(position: number, behavior?: ScrollBehavior): void; scrollToIndex(index: number, behavior?: ScrollBehavior): void; measureOffset(): number; protected updateContentSize(size: number): void; static ɵfac: i0.ɵɵFactoryDeclaration<RxVirtualScrollViewportComponent, never>; static ɵcmp: i0.ɵɵComponentDeclaration<RxVirtualScrollViewportComponent, "rx-virtual-scroll-viewport", never, { "initialScrollIndex": { "alias": "initialScrollIndex"; "required": false; }; }, { "viewRange": "viewRange"; "scrolledIndexChange": "scrolledIndexChange"; }, ["viewRepeater"], ["*"], true, never>; } declare class RxVirtualScrollWindowDirective implements RxVirtualScrollElement { private readonly document; private readonly elementRef; readonly elementScrolled$: rxjs.Observable<void>; getElementRef(): ElementRef<HTMLElement>; measureOffset(): number; static ɵfac: i0.ɵɵFactoryDeclaration<RxVirtualScrollWindowDirective, never>; static ɵdir: i0.ɵɵDirectiveDeclaration<RxVirtualScrollWindowDirective, "rx-virtual-scroll-viewport[scrollWindow]", never, {}, {}, never, never, true, never>; } export { AutoSizeVirtualScrollStrategy, DynamicSizeVirtualScrollStrategy, FixedSizeVirtualScrollStrategy, RX_VIRTUAL_SCROLL_DEFAULT_OPTIONS, RX_VIRTUAL_SCROLL_DEFAULT_OPTIONS_FACTORY, RxVirtualFor, RxVirtualForViewContext, RxVirtualScrollElement, RxVirtualScrollElementDirective, RxVirtualScrollStrategy, RxVirtualScrollViewport, RxVirtualScrollViewportComponent, RxVirtualScrollWindowDirective, RxVirtualViewRepeater }; export type { ListRange, RxVirtualScrollDefaultOptions };