# @bind

`@bind(key)` keeps a class property and one path of the DataProvider store in sync. With `{ reflect: true }` the sync goes both ways: the property follows the store, and each assignment is written back to it. For one direction only, use the complementary decorators: [@subscribe](/docs/decorators/subscribe) to read, [@publish](/docs/decorators/publish) to write. See [Data flow](/docs/getting-started/dataFlow) for the overall model.

## Import

<sonic-code language="typescript">
  <template>
import { bind } from "@supersoniks/concorde/decorators";
import { DataProviderKey } from "@supersoniks/concorde/dataProviderKey";

type Flight = { flight: string; gate: string; boarded: number };
const flightKey = new DataProviderKey&lt;Flight&gt;("flight");

@bind(flightKey.boarded, { reflect: true })
@state()
boarded = 0;
  </template>
</sonic-code>

## Basic usage

The key is a [DataProviderKey](/docs/misc/dataProviderKey): TypeScript checks that the property type matches `T` at that path. The property updates each time the store value changes. Add `@state()` so Lit re-renders.

<sonic-code>
  <template>
    <docs-demo-sources for="demo-bind"></docs-demo-sources>
    <demo-bind></demo-bind>
  </template>
</sonic-code>

## Reflect

With `reflect: true`, each assignment to the property calls `set()` at the key path, so every other subscriber sees the new value. An internal guard prevents update loops. Without `reflect` (the default), assigning the property does not touch the store, and `@bind` behaves like `@subscribe`.

<sonic-code>
  <template>
    <docs-demo-sources for="demo-bind-reflect"></docs-demo-sources>
    <demo-bind-reflect></demo-bind-reflect>
  </template>
</sonic-code>

## Dynamic path

Placeholders such as `${index}` are resolved from properties of the same component, and `@bind` re-subscribes when they change. Declare them in the key's second generic and write them in a plain string, not a backtick template literal. While a placeholder is `null` or `undefined` the binding is inactive; `{ skipEmptyPlaceholder: true }` also waits on `""`. Full rules: [Dynamic paths](/docs/misc/dynamic-path).

<sonic-code language="typescript">
  <template>
const personKey = new DataProviderKey&lt;Person, { dataProvider: string; index: number }&gt;(
  "${dataProvider}.${index}",
);

@bind(personKey)
@state()
person: Person | null = null;
  </template>
</sonic-code>

<sonic-code>
  <template>
    <docs-demo-sources for="demo-bind-dynamic"></docs-demo-sources>
    <demo-bind-dynamic></demo-bind-dynamic>
  </template>
</sonic-code>

## Lifecycle

The decorator subscribes in `connectedCallback` and unsubscribes in `disconnectedCallback`. It works on any element with that lifecycle (`LitElement`, the `Subscriber` mixin).

## API reference

| Argument | Type | Description |
|----------|------|-------------|
| `key` | `DataProviderKey<T>` | Store path to bind. Supports `${prop}` placeholders |
| `options.reflect` | `boolean` (default `false`) | Write local assignments back to the store |
| `options.skipEmptyPlaceholder` | `boolean` (default `false`) | Treat a placeholder resolved to `""` as not ready |
