ComponentStandalone

Transfer

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

Installation

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.

<wr-transfer [items]="permissions" [(value)]="granted" />
Available0 / 6
Selected0 / 1

Value: [ "read" ]

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.

<wr-transfer
  searchable
  sourceTitle="All permissions"
  targetTitle="Granted"
  [items]="permissions"
  [(value)]="granted"
/>
All permissions0 / 7
Granted0 / 0
  • Nothing here

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.

<!-- 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

NameDescriptionTypeDefault
itemsEvery row, in either pane. Membership of the right pane is value.readonly WrTransferItem[][]
valueValues 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
disabledDisable the whole control.booleanfalse
searchableShow a filter box above each pane.booleanfalse
sourceTitleHeading above the left pane. Falls back to transfer.source.string | nullnull
targetTitleHeading above the right pane. Falls back to transfer.target.string | nullnull
searchPlaceholderPlaceholder in both filter boxes. Falls back to transfer.search.string | nullnull
emptyTextShown in a pane with no rows. Falls back to transfer.empty.string | nullnull
toTargetLabelAccessible name of the move-right button. Falls back to transfer.toTarget.string | nullnull
toSourceLabelAccessible name of the move-left button. Falls back to transfer.toSource.string | nullnull