File

core/src/rxjs/observe/directives/observe-latest.directive.ts

Description

Documentation in ObserveLatestDirective.observeLatest to allow in-template tooltips.

Extends

ObserveMapDirective

Metadata

Index

Properties
Methods
Inputs
Outputs
Accessors

Inputs

observeLatest
Type : T

Combines a map of observables using rxjs combineLatest() and exposes the emitted values to the template. Values are exposed in a map which keys are the same keys as the original observable map and values are the emitted values corresponding to those keys.

Emitted values will be available as the implicit context values but will also be spread into the context by key. Meaning, this would work:

<div *observeLatest="{ x: x$, y: y$ } as result">{{result.x}}</div>

And this also:

<div *observeLatest="{ x: x$, y: y$ }; let x = x">{{x}}</div>

Any template assigned with the directive will render immediately, and its view context will be updated with the emitted value on each emission. The directive will be responsible for subscribing on init and unsubscribing on destroy.

Features

Shared observable

The watched observable will automatically be multicasted so that any child observables created by the template will use the same stream.

The shared observable can be accessed using the let source = source microsyntax.

Observer events

Whenever the observable changes state or emits a value, the corresponding event is emitted: nextCalled - A value has been emitted. $event will be the emitted value. errorCalled - An error has occured in the pipeline. $event will be the error. completeCalled - The observable has completed. $event will be void.

Because of limitations to Angular's Structural Directives, in order to bind the events the desugared syntax must be used. This, for example, will trigger the event:

<ng-template [observe]="x$" let-source="source" (nextCalled)="onNext($event)">
   ...
</ng-template>

This will NOT trigger the event:

<div *observe="x$; let source = source" (nextCalled)="onNext($event)">...</div>

Outputs

completeCalled
Type : EventEmitter<void>
Inherited from ObserveBaseDirective

Triggered when the observable completes. $event will be the void.

errorCalled
Type : EventEmitter<>
Inherited from ObserveBaseDirective

Triggered when an error occurs in the observable's pipeline. $event will be the error.

nextCalled
Type : EventEmitter<TResolved>
Inherited from ObserveBaseDirective

Triggered whenever the observable emits a value. $event will be the emitted value.

Methods

Static ngTemplateContextGuard
ngTemplateContextGuard(directive: ObserveLatestDirective<T>, context)
Type parameters:
  • T
Parameters:
Name Type Optional
directive ObserveLatestDirective<T> No
context No
Protected observeInput
observeInput(input: T)
Inherited from ObserveBaseDirective
Parameters:
Name Type Optional
input T No
Protected createViewContext
createViewContext(data: literal type)
Inherited from ObserveBaseDirective
Parameters:
Name Type Optional
data literal type No
Returns: TContext
ngOnInit
ngOnInit()
Inherited from ObserveBaseDirective
Returns: void
ngOnDestroy
ngOnDestroy()
Inherited from Destroyable
Returns: void
Protected subscribe
subscribe(observable: Observable, next?: (value?: T) => void, error?: (undefined) => void, complete?: () => void)
Inherited from Destroyable
Type parameters:
  • T

Subscribes to an observable and stores the subscription for automatic disposal. When ngOnDestroy() is called, all subscriptions created with this method will unsubscribe.

Parameters:
Name Type Optional Description
observable Observable<T> No

The observable to subscribe to.

next function Yes

(Optional) A callback function to execute on each emission of the observable.

error function Yes

(Optional) A callback function to execute when the observable errors.

complete function Yes

(Optional) A callback function to execute when the observable completes.

Returns: Subscription

The subscription created for the observable.

Properties

Protected selector
Type: string
Default value: 'observeLatest'
Inherited from ObserveBaseDirective
Protected Readonly input
Type: BehaviorSubject<TInput | null>
Default value: new BehaviorSubject(null as TInput | null)
Inherited from ObserveBaseDirective

input is set from @Input properties. For some reason, Angular passes-in the first value BEFORE ngOnInit, even though other @Input properties (e.g. showAfter, showFor) are passed AFTER ngOnInit. If subscription occurs in the constructor, input will emit the first observable too fast, which might lead to pipes breaking or misbehaving if they rely on properties to be instantiated first.

This leads to subscribing in ngOnInit, to allow Angular time to initialize those. BUT, if input is a Subject, as the first value was already emitted BEFORE ngOnInit, it will not be captured by our subscription to input. Hence the BehaviorSubject - To allow capturing that first observable.

Protected Readonly destroyed
Type: Subject<void>
Default value: new Subject()
Inherited from Destroyable

Emits a value when ngOnDestroy() is called. Pipe together with takeUntil() to auto unsubscribe from your observables.

observable.pipe(takeUntil(this.destroyed)).subscribe(...);
Protected Readonly subscriptions
Type: Subscription
Default value: new Subscription()
Inherited from Destroyable

A list of all subscriptions manually added using the subscribe() method. These are automatically unsubscribed when ngOnDestroy() is called.

Accessors

observeLatest
setobserveLatest(value: T)

Combines a map of observables using rxjs combineLatest() and exposes the emitted values to the template. Values are exposed in a map which keys are the same keys as the original observable map and values are the emitted values corresponding to those keys.

Emitted values will be available as the implicit context values but will also be spread into the context by key. Meaning, this would work:

<div *observeLatest="{ x: x$, y: y$ } as result">{{result.x}}</div>

And this also:

<div *observeLatest="{ x: x$, y: y$ }; let x = x">{{x}}</div>

Any template assigned with the directive will render immediately, and its view context will be updated with the emitted value on each emission. The directive will be responsible for subscribing on init and unsubscribing on destroy.

Features

Shared observable

The watched observable will automatically be multicasted so that any child observables created by the template will use the same stream.

The shared observable can be accessed using the let source = source microsyntax.

Observer events

Whenever the observable changes state or emits a value, the corresponding event is emitted: nextCalled - A value has been emitted. $event will be the emitted value. errorCalled - An error has occured in the pipeline. $event will be the error. completeCalled - The observable has completed. $event will be void.

Because of limitations to Angular's Structural Directives, in order to bind the events the desugared syntax must be used. This, for example, will trigger the event:

<ng-template [observe]="x$" let-source="source" (nextCalled)="onNext($event)">
   ...
</ng-template>

This will NOT trigger the event:

<div *observe="x$; let source = source" (nextCalled)="onNext($event)">...</div>
Parameters :
Name Type Optional
value T No
Returns: void
import { Observable, combineLatest } from 'rxjs';
import { Directive, Input          } from '@angular/core';

import { ObserveMapDirective                            } from '../abstraction/observe-map-base.directive';
import { ObserveMapContext, EmittedMapOf, ObservableMap } from '../abstraction/types/maps';

type ObserveLatestContext<T extends ObservableMap> = ObserveMapContext<T> & {
    observeLatest: EmittedMapOf<T>
};

/**
 * Documentation in {@link ObserveLatestDirective.observeLatest} to allow in-template tooltips.
 * @export
 * @class ObserveLatestDirective
 * @extends {ObserveMapDirective<T, ObserveLatestContext<T>>}
 * @template T The type of observables map received by the directive.
 */
@Directive({
    selector: '[observeLatest]'
})
export class ObserveLatestDirective<T extends { [key: string]: Observable<unknown> }>
     extends ObserveMapDirective<T, ObserveLatestContext<T>>
{
    // Seems like for template typechecking to work with a generic type holding `unknown`, the generic type must be flattened
    // and not represented by a new type. When I tried creating an ObservableMap = { ...key: Observable<unknown> } and use it
    // as T extends ObservableMap, the type system failed to infer the inner types of the observables.
    // T extends { ...key: Observable<unknown> } works fine.

    protected selector = 'observeLatest';

    /**
     * Combines a map of observables using rxjs {@link https://rxjs.dev/api/index/function/combineLatest combineLatest()} and exposes the emitted values to the template.
     * Values are exposed in a map which keys are the same keys as the original observable map and values are
     * the emitted values corresponding to those keys.
     * 
     * Emitted values will be available as the implicit context values but will also be spread into the context by key.
     * Meaning, this would work:
     * ```html
     * <div *observeLatest="{ x: x$, y: y$ } as result">{{result.x}}</div>
     * ```
     * 
     * And this also:
     * ```
     * <div *observeLatest="{ x: x$, y: y$ }; let x = x">{{x}}</div>
     * ```
     *
     * Any template assigned with the directive will render immediately, and its view context will be updated with the emitted value on
     * each emission. The directive will be responsible for subscribing on init and unsubscribing on destroy.
     * 
     * ## Features
     * 
     * #### Shared observable
     * The watched observable will automatically be multicasted so that any child observables created by the template will use the same
     * stream.
     * 
     * The shared observable can be accessed using the `let source = source` microsyntax.
     * 
     * #### Observer events
     * Whenever the observable changes state or emits a value, the corresponding event is emitted:  
     * `nextCalled` - A value has been emitted. `$event` will be the emitted value.  
     * `errorCalled` - An error has occured in the pipeline. `$event` will be the error.  
     * `completeCalled` - The observable has completed. `$event` will be void.
     *
     * > Because of limitations to Angular's Structural Directives, in order to bind the events the desugared syntax must be used.
     * This, for example, **will trigger** the event:
     * > ```html
     * ><ng-template [observe]="x$" let-source="source" (nextCalled)="onNext($event)">
     * >    ...
     * ></ng-template>
     * > ```
     * >
     * >This **will NOT trigger** the event:
     * >```html
     * > <div *observe="x$; let source = source" (nextCalled)="onNext($event)">...</div>
     * >```
     */
    @Input() public set observeLatest(value: T) { this.input.next(value); }
    
    static ngTemplateContextGuard<T extends { [key: string]: Observable<unknown> }>(directive: ObserveLatestDirective<T>, context: unknown): context is ObserveLatestContext<T> { return true; }
    
    protected observeInput(input: T): Observable<EmittedMapOf<T>>
    {
        return combineLatest(input) as Observable<EmittedMapOf<T>>;
    }
}

results matching ""

    No results matching ""