@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.
334 lines (333 loc) • 12.3 kB
TypeScript
import { DoCheck, EmbeddedViewRef, NgIterable, OnDestroy, OnInit, Signal, TemplateRef, TrackByFunction } from '@angular/core';
import { RxStrategyNames } from '@rx-angular/cdk/render-strategies';
import { RxListViewComputedContext } from '@rx-angular/cdk/template';
import { Observable, Subject } from 'rxjs';
import { RxForViewContext } from './for-view-context';
import * as i0 from "@angular/core";
/**
* @Directive RxFor
*
* @description
*
* The most common way to render lists in angular is by using the `*ngFor` structural directive. `*ngFor` is able
* to take an arbitrary list of data and repeat a defined template per item of the list. However, it can
* only do it synchronously.
*
* Compared to the `NgFor`, `RxFor` treats each child template as single renderable unit.
* The change detection of the child templates get prioritized, scheduled and executed by
* leveraging `RenderStrategies` under the hood.
* This technique enables non-blocking rendering of lists and can be referred to as `concurrent mode`.
*
* Read more about this in the [strategies
* section](https://www.rx-angular.io/docs/template/rx-for-directive#rxfor-with-concurrent-strategies).
*
* Furthermore, `RxFor` provides hooks to react to rendered items in form of a `renderCallback: Subject`.
*
* Together with the `RxRenderStrategies`, this makes the rendering behavior extremely versatile
* and transparent for the developer.
* Each instance of `RxFor` can be configured to render with different settings.
*
* Read more in the [official docs](https://www.rx-angular.io/docs/template/rx-for-directive)
*
* @docsCategory RxFor
* @docsPage RxFor
* @publicApi
*/
export declare class RxFor<T, U extends NgIterable<T> = NgIterable<T>> implements OnInit, DoCheck, OnDestroy {
private readonly templateRef;
/** @internal */
private cdRef;
/** @internal */
private ngZone;
/** @internal */
private injector;
/** @internal */
private viewContainerRef;
/** @internal */
private strategyProvider;
/** @internal */
private errorHandler;
/** @internal */
private staticValue?;
/** @internal */
private renderStatic;
/**
* @description
* The iterable input
*
* @example
* <ng-container *rxFor="heroes$; let hero">
* <app-hero [hero]="hero"></app-hero>
* </ng-container>
*
* @param { Observable<(U & NgIterable<T>) | undefined | null>
* | Signal<(U & NgIterable<T>) | undefined | null>
* | (U & NgIterable<T>)
* | null
* | undefined } potentialSignalOrObservable
*/
set rxForOf(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 rxForTemplate(value: TemplateRef<RxForViewContext<T, U>>);
/**
* @description
*
* You can change the used `RenderStrategy` by using the `strategy` input of the `*rxFor`. It accepts
* an `Observable<RxStrategyNames>` or
* [`RxStrategyNames`](https://github.com/rx-angular/rx-angular/blob/b0630f69017cc1871d093e976006066d5f2005b9/libs/cdk/render-strategies/src/lib/model.ts#L52).
*
* The default value for strategy is
* [`normal`](https://www.rx-angular.io/docs/template/cdk/render-strategies/strategies/concurrent-strategies).
*
* Read more about this in the
* [official docs](https://www.rx-angular.io/docs/template/rx-for-directive#use-render-strategies-strategy).
*
* @example
*
* \@Component({
* selector: 'app-root',
* template: `
* <ng-container *rxFor="let hero of heroes$; strategy: strategy">
* <app-hero [hero]="hero"></app-hero>
* </ng-container>
*
* <ng-container *rxFor="let hero of heroes$; strategy: strategy$">
* <app-hero [hero]="hero"></app-hero>
* </ng-container>
* `
* })
* export class AppComponent {
* strategy = 'low';
* strategy$ = of('immediate');
* }
*
* @param {string | Observable<string> | undefined} strategyName
* @see {@link strategies}
*/
set rxForStrategy(strategyName: RxStrategyNames | Observable<RxStrategyNames> | undefined);
/**
* @description
*
* When local rendering strategies are used, we need to treat view and content queries in a
* special way.
* To make `*rxFor` in such situations, a certain mechanism is implemented to
* execute change detection on the parent (`parent`).
*
* This is required if your components state is dependent on its view or content children:
*
* - `@ViewChild`
* - `@ViewChildren`
* - `@ContentChild`
* - `@ContentChildren`
*
* Read more about this in the
* [official
* docs](https://www.rx-angular.io/docs/template/rx-for-directive#local-strategies-and-view-content-queries-parent).
*
* @example
* \@Component({
* selector: 'app-root',
* template: `
* <app-list-component>
* <app-list-item
* *rxFor="
* let item of items$;
* trackBy: trackItem;
* parent: true;
* "
* >
* <div>{{ item.name }}</div>
* </app-list-item>
* </app-list-component>
* `
* })
* export class AppComponent {
* items$ = itemService.getItems();
* }
*
* @param {boolean} 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 *rxFor templates are created within `NgZone` or not.
* The default value is `true, `*rxFor` will create it's `EmbeddedViews` inside `NgZone`.
*
* Event listeners normally trigger zone. Especially high frequently events cause performance issues.
*
* Read more about this in the
* [official
* docs](https://www.rx-angular.io/docs/template/rx-for-directive#working-with-event-listeners-patchzone).
*
* @example
* \@Component({
* selector: 'app-root',
* template: `
* <app-list-component>
* <app-list-item
* *rxFor="
* let item of items$;
* trackBy: trackItem;
* patchZone: false;
* "
* >
* <div>{{ item.name }}</div>
* </app-list-item>
* </app-list-component>
* `
* })
* export class AppComponent {
* items$ = itemService.getItems();
* }
*
* @param {boolean} patchZone
*/
patchZone: boolean;
private defaultTrackBy;
/**
* @description
* A function or key that defines how to track changes for items in the iterable.
*
* When items are added, moved, or removed in the iterable,
* the directive must re-render the appropriate DOM nodes.
* To minimize churn in the DOM, only nodes that have changed
* are re-rendered.
*
* By default, rxFor assumes that the object instance identifies the node in the iterable (equality check `===`).
* When a function or key is supplied, rxFor uses the result to identify the item node.
*
* @example
* \@Component({
* selector: 'app-root',
* template: `
* <app-list-component>
* <app-list-item
* *rxFor="
* let item of items$;
* trackBy: 'id';
* "
* >
* <div>{{ item.name }}</div>
* </app-list-item>
* </app-list-component>
* `
* })
* export class AppComponent {
* items$ = itemService.getItems();
* }
*
* // OR
*
* \@Component({
* selector: 'app-root',
* template: `
* <app-list-component>
* <app-list-item
* *rxFor="
* let item of items$;
* trackBy: trackItem;
* "
* >
* <div>{{ item.name }}</div>
* </app-list-item>
* </app-list-component>
* `
* })
* export class AppComponent {
* items$ = itemService.getItems();
* trackItem = (idx, item) => item.id;
* }
*
* @param trackByFnOrKey
*/
set trackBy(trackByFnOrKey: keyof T | ((idx: number, i: T) => any));
/**
* @description
* A `Subject` which emits whenever *rxFor finished rendering a set changes to the view.
* This enables developers to perform actions when a list has finished rendering.
* The `renderCallback` is useful in situations where you rely on specific DOM properties like the `height` 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: `
* <app-list-component>
* <app-list-item
* *rxFor="
* let item of items$;
* trackBy: trackItem;
* renderCallback: itemsRendered;
* ">
* <div>{{ item.name }}</div>
* </app-list-item>
* </app-list-component>
* `
* })
* export class AppComponent {
* items$: Observable<Item[]> = itemService.getItems();
* trackItem = (idx, item) => item.id;
* // this emits whenever rxFor finished rendering changes
* itemsRendered = new Subject<Item[]>();
*
* constructor(elementRef: ElementRef<HTMLElement>) {
* itemsRendered.subscribe(() => {
* // items are rendered, we can now scroll
* elementRef.scrollTo({bottom: 0});
* })
* }
* }
*
* @param {Subject<U>} renderCallback
*/
set renderCallback(renderCallback: Subject<U>);
private get template();
/** @internal */
private strategyInput$;
/** @internal */
private observables$;
/** @internal */
private _renderCallback;
/** @internal */
private readonly values$;
/** @internal */
private values;
/** @internal */
private readonly strategy$;
/** @internal */
private _subscription;
/** @internal */
_trackBy: TrackByFunction<T>;
/** @internal */
_distinctBy: (a: T, b: T) => boolean;
private reconciler;
constructor(templateRef: TemplateRef<RxForViewContext<T, U>>);
/** @internal */
ngOnInit(): void;
/** @internal */
createViewContext(item: T, computedContext: RxListViewComputedContext): RxForViewContext<T, U>;
/** @internal */
updateViewContext(item: T, view: EmbeddedViewRef<RxForViewContext<T>>, computedContext: RxListViewComputedContext): void;
/** @internal */
ngDoCheck(): void;
/** @internal */
ngOnDestroy(): void;
/** @internal */
static ngTemplateContextGuard<T, U extends NgIterable<T> = NgIterable<T>, K = keyof T>(dir: RxFor<T, U>, ctx: any): ctx is RxForViewContext<T, U, K>;
static ɵfac: i0.ɵɵFactoryDeclaration<RxFor<any, any>, never>;
static ɵdir: i0.ɵɵDirectiveDeclaration<RxFor<any, any>, "[rxFor][rxForOf]", never, { "rxForOf": { "alias": "rxForOf"; "required": false; }; "rxForTemplate": { "alias": "rxForTemplate"; "required": false; }; "rxForStrategy": { "alias": "rxForStrategy"; "required": false; }; "renderParent": { "alias": "rxForParent"; "required": false; }; "patchZone": { "alias": "rxForPatchZone"; "required": false; }; "trackBy": { "alias": "rxForTrackBy"; "required": false; }; "renderCallback": { "alias": "rxForRenderCallback"; "required": false; }; }, {}, never, never, true, never>;
}