# AssistedField

> Lends a control that keeps its value in state, such as a custom picker, as a field the assistant fills through your setter.

`AssistedField` lends a control that keeps its value in state, not in a DOM field, as a field the assistant fills. It takes the value to show and the function that sets it.

![The New order dialog beside the sheet panel. The product picker's Desk button is selected, and the expanded order_field call answers Filled Product; it now says Desk.](https://superassist.app/_astro/field-light.DOo_8DQ0.webp)

## Usage

Pass the value and its setter, and wrap the control. From `examples/app/app/orders/new-order.tsx`:

```tsx
<AssistedField
  name="order_field"
  id="product"
  label="Product"
  options={products.map((value) => ({ value }))}
  value={draft.product}
  onFill={(value) => set("product", value)}
>
  <div role="group" aria-label="Product" className="flex gap-1">
    {products.map((name) => (
      <Button
        key={name}
        type="button"
        aria-pressed={draft.product === name}
        size="sm"
        variant={draft.product === name ? "secondary" : "ghost"}
        onClick={() => set("product", name)}
      >
        {name}
      </Button>
    ))}
  </div>
</AssistedField>
```

The child is only the ring's target. The value comes from `value`, and a fill goes through `onFill`.

## What the model sees

The picker shares the name `order_field` with the dialog's [AssistedInput](https://superassist.app/components/package/assisted-input.md) fields, so it is one entry of that tool. With `options`, its entry lists the values it takes:

```txt wrap
Fill one of these by its id. customer: Customer, one of "" (Pick a customer), "Acme", "Globex", "Initech", "Umbrella"; product: Product, one of "Chair", "Desk", "Lamp", "Monitor"; quantity: Quantity; note: Note.
```

The dialog's note shows what it says now, as for any field:

```md wrap
Its fields: order_field (customer: Customer, now ""; product: Product, now ""; quantity: Quantity, now "1"; note: Note, now "").
```

The fill in the screenshot called `onFill`, waited for React to commit, and answered with `value` as rendered:

```txt wrap
Filled "Product"; it now says "Desk".
```

## Props

| Prop            | Type                         | Required | Description                                                                                    |
| --------------- | ---------------------------- | -------- | ---------------------------------------------------------------------------------------------- |
| `name`          | `string`                     | Yes      | The field's tool name. Same-name fields on one page are one tool.                              |
| `label`         | `string`                     | Yes      | What the field holds. Shown in the tool's description and the page's note.                     |
| `id`            | `string`                     | No       | The field's id within a same-name group.                                                       |
| `consequential` | `boolean`                    | No       | `true` rings the child for the user to fill.                                                   |
| `trace`         | `boolean`                    | No       | Shows the fill on the page with a ring. Defaults to the provider's `trace`.                    |
| `options`       | `AssistedFieldOption[]`      | No       | The only values the field takes. `AssistedFieldOption` is `{ value: string; label?: string }`. |
| `value`         | `string`                     | Yes      | What the field says now. The note shows it as a JSON string.                                   |
| `onFill`        | `(value: string) => unknown` | Yes      | Sets the field to the value the assistant chose. Awaited.                                      |
| `children`      | `ReactElement`               | Yes      | One element whose `ref` reaches a DOM element, the ring's target.                              |

- Throws `Render an assisted field inside an AssistedPage` outside a page.
- A fill checks the child as `AssistedInput` does, calls `onFill`, waits for pending React updates to commit, then answers with `value` as rendered.
- The field is lent again only when `name`, `label`, `id`, `consequential`, `trace` or the content of `options` changes. `value` and `onFill` are read at call time.
- A tool's `value` parameter gains an enum only when every field of that name has `options`. New order's `order_field` mixes the picker with two text inputs, so it has none.

## See also

- [Lend a form's fields](https://superassist.app/how-to/lend-form-fields.md#lend-a-control-that-is-not-a-native-field).
- [Model context](https://superassist.app/reference/model-context.md#field-tools) gives the field tool's template.
