Types
This section covers the various value types that can be created from use and select.
Value#
The Value type is a reactive primitive that powers reactive APIs in this package.
import { use } from "@mmuscat/angular-composition-api"
const value = use(0)It is similar to a
BehaviorSubject in that it:
- Takes an initial value
- Emits the current value when it is subscribed to
- Can imperatively inspect the current value through its
valueproperty accessor - Can imperatively set a new value by calling
next
In addition to this, a Value can:
- Access its value by invoking it with zero arguments
- Set its value by invoking it with one argument
- Be marked as a dependency by reactive observers (see Subscriptions)
- Unwrapped by
ViewDefto a reactive value on the class instance (see Views)
Where it differs:
- The
Valuetype does not implement error or complete observers - The
Valuetype is an interop observable that inherits fromFunction
Since Value does not extend the Observable prototype, instanceof checks will fail. Should you require this, cast
Value to an Observable first using pipe or from.
Custom check#
Input bindings are checked using strict equality by default. This can be customised by passing a distinct
option when creating a Value. For example, shallow checking an array.
import { Component } from "@angular/core"import { use, ViewDef } from "@mmuscat/angular-composition-api"import shallowEqual from "shallowequal"
function setup() { const results = use([], { distinct: shallowEqual })
subscribe(results, () => { console.log(results) }) return { results }}
@Component({ inputs: ["results"]})export class MyComponent extends ViewDef(setup) {}note
Use distinct sparingly, as it is called on every change detection cycle and may cause performance issues if the
check expression is expensive.
Deferred Value#
A deferred Value has an initial state of undefined, and does not start emitting values until its initial value has
been set. Afterwards it behaves like a normal Value. This behavior is similar to ReplaySubject. Deferred values are
created from Observable objects.
import { use } from "@mmuscat/angular-composition-api"import { of } from "rxjs"
const deferredValue = use(of(10))Computed Value#
A computed Value is derived from other Value objects using a reactive observer.
import { select, use } from "@mmuscat/angular-composition-api"
const count = use(0)const doubled = select(() => count() * 2)Accessor Value#
An AccessorValue is a Value with separate types for reading and writing values.
import { select, use } from "@mmuscat/angular-composition-api"
const value = use(0)const accessorValue = select({ next(nextValue: string) { value.next(parseFloat(nextValue)) }, value,})Emitter#
An Emitter is a functional wrapper around EventEmitter. Unlike Value it is not unwrapped by ViewDef, does not
hold state and cannot be marked as a dependency in reactive observers. It is ideal for outputs and signals to trigger
other state changes.
import { use } from "@mmuscat/angular-composition-api"
const voidEmitter = use<void>(Function)
voidEmitter() // emitimport { use } from "@mmuscat/angular-composition-api"
const basicEmitter = use<number>(Function)
basicEmitter(10) // emitimport { use } from "@mmuscat/angular-composition-api"
const emitterWithParams = use((...args: number[]) => args.reduce((a, b) => a + b, 0),)
emitterWithParams(1, 2, 3) // emit