# Custom Lookup Bindings

## Custom Option Template

Children of `LookupField` define how each option is rendered in the dropdown. The `$option` alias refers to the current option object being rendered. Use it to access any property of the option.

```tsx
import { createModel } from "cx/data";
import { bind, LabelsTopLayout, tpl } from "cx/ui";
import { LookupField } from "cx/widgets";

interface City {
  id: number;
  text: string;
  population: number;
}

interface Model {
  selectedCityId: number;
  $option: City;
}

const m = createModel<Model>();

const options: City[] = [
  { id: 1, text: "New York", population: 8336817 },
  { id: 2, text: "Los Angeles", population: 3979576 },
  { id: 3, text: "Chicago", population: 2693976 },
  { id: 4, text: "Houston", population: 2320268 },
  { id: 5, text: "Phoenix", population: 1680992 },
];

export default (
  <LabelsTopLayout vertical>
    <LookupField
      label="Select a City"
      value={m.selectedCityId}
      options={options}
    >
      <div>
        <strong text={m.$option.text} />
        <div
          class="text-xs text-gray-500"
          text={tpl(m.$option.population, "Population: {0:n;0}")}
        />
      </div>
    </LookupField>
  </LabelsTopLayout>
);

```

## Single Selection Bindings

The `bindings` prop copies additional fields from the selected option into the store. Each binding specifies:

- `remote` - the source field on the option (use `$option.xxx`)
- `local` - the destination path in the store

When an option is selected, all bindings are applied, copying data from `$option` to the store.

```tsx
import { createModel } from "cx/data";
import { bind, LabelsTopLayout, tpl } from "cx/ui";
import { isDefined } from "cx/util";
import { LookupField, PureContainer } from "cx/widgets";

interface City {
  id: number;
  text: string;
  population: number;
  landArea: number;
}

interface Model {
  city: City;
}

const m = createModel<Model>();

const options: City[] = [
  { id: 1, text: "New York", population: 8336817, landArea: 783 },
  { id: 2, text: "Los Angeles", population: 3979576, landArea: 1213 },
  { id: 3, text: "Chicago", population: 2693976, landArea: 606 },
  { id: 4, text: "Houston", population: 2320268, landArea: 1707 },
  { id: 5, text: "Phoenix", population: 1680992, landArea: 1340 },
];

export default (
  <LabelsTopLayout vertical>
    <LookupField
      label="Select a City"
      value={m.city.id}
      text={m.city.text}
      options={options}
      bindings={[
        { key: true, local: m.city.id, remote: "$option.id" },
        { local: m.city.text, remote: "$option.text" },
        { local: m.city.population, remote: "$option.population" },
        { local: m.city.landArea, remote: "$option.landArea" },
      ]}
    />

    <PureContainer if={isDefined(m.city.id)}>
      <div class="mt-2 space-y-1">
        <strong text={m.city.text} />
        <div text={tpl(m.city.population, "Population: {0:n;0}")} />
        <div text={tpl(m.city.landArea, "Land Area: {0} km²")} />
      </div>
    </PureContainer>
  </LabelsTopLayout>
);

```

## Multiple Selection Bindings

In multiple selection mode, selected options are stored as records in an array. The `$value` alias refers to the record being created for each selection. Bindings copy data from `$option` (the selected option) to `$value` (the new record).

```tsx
import { createModel } from "cx/data";
import { LabelsTopLayout, tpl } from "cx/ui";
import { LookupField, Repeater } from "cx/widgets";

interface City {
  id: number;
  text: string;
  population: number;
  landArea: number;
}

interface Model {
  selectedCities: City[];
  $option: City;
  $city: City;
}

const m = createModel<Model>();

const options: City[] = [
  { id: 1, text: "New York", population: 8336817, landArea: 783 },
  { id: 2, text: "Los Angeles", population: 3979576, landArea: 1213 },
  { id: 3, text: "Chicago", population: 2693976, landArea: 606 },
  { id: 4, text: "Houston", population: 2320268, landArea: 1707 },
  { id: 5, text: "Phoenix", population: 1680992, landArea: 1340 },
];

export default (
  <LabelsTopLayout vertical>
    <LookupField
      label="Select Cities"
      records={m.selectedCities}
      options={options}
      multiple
      bindings={[
        { key: true, local: "$value.id", remote: "$option.id" },
        { local: "$value.text", remote: "$option.text" },
        { local: "$value.population", remote: "$option.population" },
        { local: "$value.landArea", remote: "$option.landArea" },
      ]}
    />
    <Repeater records={m.selectedCities} recordAlias={m.$city}>
      <div class="border-b border-gray-300 py-2">
        <strong text={m.$city.text} />
        <div text={tpl(m.$city.population, "Population: {0:n;0}")} />
        <div text={tpl(m.$city.landArea, "Land Area: {0} km²")} />
      </div>
    </Repeater>
  </LabelsTopLayout>
);

```

## Configuration

| Property | Type      | Description                              |
| -------- | --------- | ---------------------------------------- |
| `key`    | `boolean` | Marks the primary key binding (required) |
| `local`  | `string`  | Destination: store path or `$value.xxx`  |
| `remote` | `string`  | Source: option field using `$option.xxx` |