@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.
446 lines (445 loc) • 15.8 kB
TypeScript
import { OnChanges, OnDestroy, OnInit, Signal, SimpleChanges, TemplateRef } from '@angular/core';
import { RxNotificationKind } from '@rx-angular/cdk/notifications';
import { RxStrategyNames } from '@rx-angular/cdk/render-strategies';
import { NextObserver, Observable, ObservableInput } from 'rxjs';
import { RxIfViewContext } from './model/index';
import * as i0 from "@angular/core";
/**
* @Directive IfDirective
* @description
*
* The `RxIf` directive is drop-in replacement for the `NgIf` directive, but with additional features.
* `RxIf` allows you to bind observables directly without having the need of using the `async`
* pipe in addition.
*
* This enables `rxIf` to completely operate on its own without having to interact with `NgZone`
* or triggering global change detection.
*
* Read more about the RxIf directive in the [official
* docs](https://www.rx-angular.io/docs/template/rx-if-directive).
*
* @example
* <app-item *rxIf="show$"></app-item>
*
* @docsCategory RxIf
* @docsPage RxIf
* @publicApi
*/
export declare class RxIf<T = unknown> implements OnInit, OnChanges, OnDestroy, OnChanges {
private readonly templateRef;
/** @internal */
private strategyProvider;
/** @internal */
private cdRef;
/** @internal */
private ngZone;
/** @internal */
private viewContainerRef;
/** @internal */
private injector;
/** @internal */
private subscription;
/** @internal */
private _renderObserver;
/** @internal */
private templateManager;
/**
* @description
* The Observable or value to representing the condition.
*
* @example
* showHero = true;
* showHero$ = new BehaviorSubject<boolean>(true);
*
* <ng-container *rxIf="showHero">
* <app-hero></app-hero>
* </ng-container>
*
* <ng-container *rxIf="showHero$">
* <app-hero></app-hero>
* </ng-container>
*
* @param { ObservableInput<T> | T } rxIf
*/
rxIf: ObservableInput<T> | Signal<T> | T;
/**
* @description
*
* You can change the used `RenderStrategy` by using the `strategy` input of the `*rxIf`. 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-if-directive#use-render-strategies-strategy).
*
* @example
*
* \@Component({
* selector: 'app-root',
* template: `
* <ng-container *rxIf="showHero$; strategy: 'userBlocking'">
* <app-hero></app-hero>
* </ng-container>
*
* <ng-container *rxIf="showHero$; strategy: strategy$">
* <app-hero></app-hero>
* </ng-container>
* `
* })
* export class AppComponent {
* strategy$ = of('immediate');
* }
*
* @param { string | Observable<string> | undefined } strategyName
* @see {@link RxStrategyNames}
*/
set strategy(strategyName: Observable<RxStrategyNames> | RxStrategyNames);
/**
* @description
* Defines the template to be used when the bound value is falsy
*
* @example
* <app-hero *rxIf="show$; else: noHero"></app-hero>
* <ng-template #noHero><no-hero></no-hero></ng-template>
*/
else: TemplateRef<RxIfViewContext<T>>;
/**
* @description
* Defines the template to be used when the bound value is truthy
*
* @example
* <ng-container *rxIf="show$; then: hero"></ng-container>
* <ng-template #hero><app-hero></app-hero></ng-template>
*/
then: TemplateRef<RxIfViewContext<T>>;
/**
* @description
* Defines the template for the suspense state. Will be
* shown when the bound Observable is in "suspense" state.
* Suspense state is active when the current value is undefined or no value
* was ever emitted.
*
* Read more about the reactive context in the
* [official docs](https://www.rx-angular.io/docs/template/concepts/reactive-context).
*
* @example
* <app-hero *rxIf="show$; suspense: suspenseTemplate" ></app-hero>
* <ng-template #suspenseTemplate>
* <mat-progress-spinner></mat-progress-spinner>
* </ng-template>
*
* @param { TemplateRef<RxIfViewContext> } suspense
*/
suspense: TemplateRef<RxIfViewContext<T>>;
/**
* @description
* Defines the template for the complete state. Will be
* shown when the bound Observable is in "complete" state.
*
* Read more about the reactive context in the
* [official docs](https://www.rx-angular.io/docs/template/concepts/reactive-context).
*
* @example
* <app-hero *rxIf="show$; complete: completeTemplate" ></app-hero>
* <ng-template #completeTemplate>
* <icon>thumbs_up</icon>
* </ng-template>
*
* @param { TemplateRef<RxIfViewContext> } suspense
*/
complete: TemplateRef<RxIfViewContext<T>>;
/**
* @description
* Defines the template for the error state. Will be
* shown when the bound Observable is in "error" state.
*
* Read more about the reactive context in the
* [official docs](https://www.rx-angular.io/docs/template/concepts/reactive-context).
*
* @example
* <app-hero *rxIf="show$; error: errorTemplate" ></app-hero>
* <ng-template #errorTemplate>
* <icon>error</icon>
* </ng-template>
*
* @param { TemplateRef<RxIfViewContext> } suspense
*/
error: TemplateRef<RxIfViewContext<T>>;
/**
* @description
* A trigger to manually set the active template. It accepts a `RxNotificationKind`
* which determines what template to display. If no template is given, a context
* variable resembling the notification state is put into the `Next`
* template of the directive
*
* @example
* <ng-container
* *rxIf="
* show$;
* let e = error;
* contextTrigger: contextTrigger$
* ">
*
* <app-hero></app-hero>
* <error *ngIf="e"></error>
* </ng-container>
*
* // trigger template from component.ts
* contextTrigger$.next(RxNotificationKind.error)
*
* @param { Observable<RxNotificationKind> } contextTrigger
* @see {@link RxNotificationKind}
*/
contextTrigger?: Observable<RxNotificationKind>;
/**
* @description
* A trigger to manually activate the default template. It accepts any value,
* on emission it will switch to the let directives default template.
*
* @example
* <ng-container
* *rxIf="
* show$;
* suspense: suspense
* nextTrigger: nextTrigger$
* ">
*
* <app-hero></app-hero>
* </ng-container>
*
* <ng-template #suspense><loader></loader></ng-template>
*
* // trigger template from component.ts
* nextTrigger$.next()
*
* @param { Observable<unknown> } nextTrigger
*/
nextTrigger?: Observable<unknown>;
/**
* @description
* A trigger to manually activate the suspense template. It accepts any value,
* on emission it will display the suspense template. If no template is given,
* the suspense context variable will be set to true instead.
*
* @example
* <ng-container
* *rxIf="
* show$;
* let s = suspense;
* suspenseTrigger: suspenseTrigger$
* ">
*
* <app-hero></app-hero>
* <loader *ngIf="s"></loader>
* </ng-container>
*
*
* // trigger template from component.ts
* suspenseTrigger$.next()
*
* @param { Observable<unknown> } suspenseTrigger
*/
suspenseTrigger?: Observable<unknown>;
/**
* @description
* A trigger to manually activate the error template. It accepts any value,
* on emission it will display the error template. If no template is given,
* the error context variable will be set to true instead.
*
* @example
* <ng-container
* *rxIf="
* show$;
* let e = error;
* errorTrigger: errorTrigger$
* ">
*
* <app-hero></app-hero>
* <error *ngIf="e"></error>
* </ng-container>
*
* // trigger template from component.ts
* errorTrigger$.next()
*
* @param { Observable<unknown> } errorTrigger
*/
errorTrigger?: Observable<unknown>;
/**
* @description
* A trigger to manually activate the complete template. It accepts any value,
* on emission it will display the error template. If no template is given,
* the complete context variable will complete set to true instead.
*
* @example
* <ng-container
* *rxIf="
* show$;
* let c = complete;
* completeTrigger: completeTrigger$
* ">
*
* <app-hero></app-hero>
* <done *ngIf="c"></done>
* </ng-container>
*
* // trigger template from component.ts
* completeTrigger$.next()
*
* @param { Observable<unknown> } completeTrigger
*/
completeTrigger?: Observable<unknown>;
/**
* @description
*
* Structural directives maintain `EmbeddedView`s within a components' template.
* Depending on the bound value as well as the configured `RxRenderStrategy`,
* updates processed by the `*rxIf` directive might be asynchronous.
*
* Whenever a template gets inserted into, or removed from, its parent component, the directive has to inform the
* parent in order to update any view- or contentquery (`@ViewChild`, `@ViewChildren`, `@ContentChild`,
* `@ContentChildren`).
*
* Read more about this in the
* [official
* docs](https://www.rx-angular.io/docs/template/rx-if-directive#local-strategies-and-view-content-queries-parent).
*
* @example
* \@Component({
* selector: 'app-root',
* template: `
* <app-component>
* <app-item
* *rxIf="
* show$;
* parent: true;
* "
* >
* </app-item>
* </app-component>
* `
* })
* export class AppComponent {
* show$ = state.select('showItem');
* }
*
* @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 `*rxIf` templates are created within `NgZone` or not.
* The default value is `true, `*rxIf` will create its `EmbeddedView` inside `NgZone`.
*
* Event listeners normally trigger zone.
* Especially high frequency events can cause performance issues.
*
* Read more about this in the
* [official docs](https://www.rx-angular.io/docs/template/let-directive#working-with-event-listeners-patchzone).
*
* @example
* \@Component({
* selector: 'app-root',
* template: `
* <app-component>
* <app-item
* *rxIf="
* show$;
* patchZone: false;
* "
* (drag)="itemDrag($event)"
* >
* </app-item>
* </app-component>
* `
* })
* export class AppComponent {
* show$ = state.select('showItem');
* }
*
* @param {boolean} patchZone
*/
patchZone: boolean;
/**
* @description
* A `Subject` which emits whenever `*rxIf` rendered a change to the view.
* This enables developers to perform actions when rendering has been done.
* The `renderCallback` is useful in situations where you
* rely on specific DOM properties like the dimensions of an item after it got rendered.
*
* The `renderCallback` emits the latest value causing the view to update.
*
* @example
* \@Component({
* selector: 'app-root',
* template: `
* <app-component>
* <app-item
* *rxIf="
* show$;
* renderCallback: rendered;
* "
* >
* </app-item>
* </app-component>
* `
* })
* export class AppComponent {
* show$ = state.select('showItem');
* // this emits whenever rxIf finished rendering changes
* rendered = new Subject<boolean>();
*
* constructor(elementRef: ElementRef<HTMLElement>) {
* rendered.subscribe(() => {
* // item is rendered, we can access its dom now
* })
* }
* }
*
* @param {Subject<boolean>} callback
*/
set renderCallback(callback: NextObserver<boolean>);
/** @internal */
private triggerHandler;
/** @internal */
private templateNotifier;
/** @internal */
private readonly strategyHandler;
/** @internal */
private readonly rendered$;
/** @internal */
private get thenTemplate();
constructor(templateRef: TemplateRef<RxIfViewContext<T>>);
/** @internal */
ngOnInit(): void;
/** @internal */
ngOnChanges(changes: SimpleChanges): void;
/** @internal */
ngOnDestroy(): void;
/** @internal */
private _createTemplateManager;
/** @internal */
static rxIfUseIfTypeGuard: void;
/**
* Assert the correct type of the expression bound to the `ngIf` input within the template.
*
* The presence of this static field is a signal to the Ivy template type check compiler that
* when the `NgIf` structural directive renders its template, the type of the expression bound
* to `ngIf` should be narrowed in some way. For `NgIf`, the binding expression itself is used to
* narrow its type, which allows the strictNullChecks feature of TypeScript to work with `NgIf`.
*/
static ngTemplateGuard_rxIf: 'binding';
/**
* Asserts the correct type of the context for the template that `NgIf` will render.
*
* The presence of this method is a signal to the Ivy template type-check compiler that the
* `NgIf` structural directive renders its template with a specific context type.
*/
static ngTemplateContextGuard<T>(dir: RxIf<T>, ctx: any): ctx is RxIfViewContext<Exclude<T, false | 0 | '' | null | undefined>>;
static ɵfac: i0.ɵɵFactoryDeclaration<RxIf<any>, never>;
static ɵdir: i0.ɵɵDirectiveDeclaration<RxIf<any>, "[rxIf]", never, { "rxIf": { "alias": "rxIf"; "required": false; }; "strategy": { "alias": "rxIfStrategy"; "required": false; }; "else": { "alias": "rxIfElse"; "required": false; }; "then": { "alias": "rxIfThen"; "required": false; }; "suspense": { "alias": "rxIfSuspense"; "required": false; }; "complete": { "alias": "rxIfComplete"; "required": false; }; "error": { "alias": "rxIfError"; "required": false; }; "contextTrigger": { "alias": "rxIfContextTrigger"; "required": false; }; "nextTrigger": { "alias": "rxIfNextTrigger"; "required": false; }; "suspenseTrigger": { "alias": "rxIfSuspenseTrigger"; "required": false; }; "errorTrigger": { "alias": "rxIfErrorTrigger"; "required": false; }; "completeTrigger": { "alias": "rxIfCompleteTrigger"; "required": false; }; "renderParent": { "alias": "rxIfParent"; "required": false; }; "patchZone": { "alias": "rxIfPatchZone"; "required": false; }; "renderCallback": { "alias": "rxIfRenderCallback"; "required": false; }; }, {}, never, never, true, never>;
}