Concorde documentation · same URL (interactive) · llms.txt

Concorde decorator — @handle. @handle(...keys) calls the decorated method each time a publisher assigns one of up to three store paths, with one typed argument per key. Nothing is stored on the component: use it for derived values Doc ID: docs/decorators/handle. Keywords: Concorde, supersoniks, docs/decorators/handle, handle, @handle, decorator, @handle(...keys), null, undefined, ${prop}, waitForAllDefined: true, ${name}, please proceed to gate ${gate}., skip. URL: https://concorde.supersoniks.org/docs/decorators/handle.

@handle

@handle(...keys) calls the decorated method each time a publisher assigns one of up to three store paths, with one typed argument per key. Nothing is stored on the component: use it for derived values and side effects, and @subscribe when you only need the value. See Data flow for the overall model.

Import

import { handle, Skip } from "@supersoniks/concorde/decorators";
import { DataProviderKey } from "@supersoniks/concorde/dataProviderKey";

const cockpitKey = new DataProviderKey<{ altitude: number }>("cockpit");

@handle(cockpitKey.altitude)
onAltitude(feet: number) {
  this.meters = Math.round(feet * 0.3048);
}

Basic usage

The method runs once with the current value when the component connects, then on every assignment, including null and undefined. Below, each climb assigns a new altitude and the method derives meters and flight level.

<docs-demo-sources for="demo-handle"></docs-demo-sources>
    <demo-handle></demo-handle>

Dynamic path

${prop} placeholders resolve from properties of the same component; when one changes, the method is called with the value at the new path. Rules: Dynamic paths.

const personKey = new DataProviderKey&lt;OnBoard, { seatIndex: number }&gt;(
  "demoOnBoard.${seatIndex}",
);

@property({ type: Number }) seatIndex = 0;

@handle(personKey)
onPerson(person: OnBoard | null) {
  this.announcement = person ? `${person.name}, please proceed to gate B12.` : "";
}
<docs-demo-sources for="demo-handle-dynamic"></docs-demo-sources>
    <demo-handle-dynamic></demo-handle-dynamic>

Multiple keys

Pass up to three DataProviderKey values; the method receives one argument per key, in the same order. Any assignment to any key calls it, so other arguments may still be null.

const flightKey = new DataProviderKey&lt;{ status: string; gate: string }&gt;("flight");
const weatherKey = new DataProviderKey&lt;{ turbulence: boolean }&gt;("weather");

@handle(flightKey.status, weatherKey.turbulence)
onConditions(status: string, turbulence: boolean) {
  this.seatbeltSign = status === "boarding" || turbulence === true;
}

Wait for all values

With waitForAllDefined: true, the method runs only once every key holds a value other than null or undefined.

@handle(flightKey.gate, passengerKey.name, { waitForAllDefined: true })
announce(gate: string, name: string) {
  this.message = `${name}, please proceed to gate ${gate}.`;
}

Skip values

skip lists categories of values that must not call the method. A category is a named test, not a value to compare.

Category Matches
Skip.Nullish null or undefined
Skip.EmptyString ""
Skip.EmptyObject {} (arrays excluded)
Skip.EmptyArray []
@handle(passengerKey, { skip: [Skip.Nullish, Skip.EmptyObject] })
onPassenger(passenger: Passenger) {
  // not called while the publisher still holds {} (not loaded yet)
  this.displayName = passenger.name;
}

To reject a specific value, return early inside the method.

API reference

Argument Type Description
key (1 to 3) DataProviderKey<T, U> Paths to watch; the method receives one value per key, in order
options.waitForAllDefined boolean (default false) Call the method only when no value is null or undefined
options.skip Skip[] (default none) Do not call the method when any value matches one of these categories
options.skipEmptyPlaceholder boolean (default false) Treat a placeholder resolved to "" as not ready

options, if present, is the last argument. @handle replaces the deprecated @onAssign: @onAssign("a", "b") is @handle(keyA, keyB, { waitForAllDefined: true }).