# Transfer

> Dual listbox — two panes and the buttons that move rows between them. The RIGHT pane is the value.

Source: https://ngwr.dev/reference/components/transfer  
Kind: Component, Standalone

## Installation

```angular-ts
import { WrTransfer } from 'ngwr/transfer';

@Component({ imports: [WrTransfer] })
export class MyComponent {}
```

## Basic usage

`[items]` is the full set; `[(value)]` holds the values that ended up on the right, and everything else stays on the left. Ticking a row only stages it — the move commits when you press an arrow, so the value never contains a half-made choice. A `disabled` item can be neither ticked nor swept up by the header checkbox.

```angular-html
<wr-transfer [items]="permissions" [(value)]="granted" />
```

## Search and titles

`searchable` puts a filter above each pane; it narrows what you see and what the header checkbox sweeps, never what is already chosen. `sourceTitle` / `targetTitle` name the panes — both fall back to the `ngwr/i18n` catalog, so they are localized without being set.

```angular-html
<wr-transfer
  searchable
  sourceTitle="All permissions"
  targetTitle="Granted"
  [items]="permissions"
  [(value)]="granted"
/>
```

## In a form

A Signal Forms native control — `[formField]` binds straight to `value`, with no `ControlValueAccessor` in between. `[(ngModel)]` and reactive forms keep working through Angular's bridge, and `(touch)` fires on every committed move so a bound field marks itself touched.

```angular-html
<!-- Signal Forms — the value is the right pane -->
<wr-transfer [items]="permissions" [formField]="form.granted" />

<!-- Classic reactive forms keep working through Angular's bridge -->
<wr-transfer [items]="permissions" [formControl]="granted" />
```

## API

| Name | Description | Type | Default |
| --- | --- | --- | --- |
| `items` | Every row, in either pane. Membership of the right pane is `value`. | `readonly WrTransferItem[]` | `[]` |
| `value` | Values currently in the RIGHT pane. Two-way bindable; bound automatically by `[formField]` / `[(ngModel)]`. | `readonly unknown[]` | `[]` |
| `(touch)` | Emitted on blur / commit so a bound field marks itself touched. | `void` | — |
| `disabled` | Disable the whole control. | `boolean` | `false` |
| `searchable` | Show a filter box above each pane. | `boolean` | `false` |
| `sourceTitle` | Heading above the left pane. Falls back to `transfer.source`. | `string \| null` | `null` |
| `targetTitle` | Heading above the right pane. Falls back to `transfer.target`. | `string \| null` | `null` |
| `searchPlaceholder` | Placeholder in both filter boxes. Falls back to `transfer.search`. | `string \| null` | `null` |
| `emptyText` | Shown in a pane with no rows. Falls back to `transfer.empty`. | `string \| null` | `null` |
| `toTargetLabel` | Accessible name of the move-right button. Falls back to `transfer.toTarget`. | `string \| null` | `null` |
| `toSourceLabel` | Accessible name of the move-left button. Falls back to `transfer.toSource`. | `string \| null` | `null` |
