Transfer

Move items between two lists; the right one is the value.

Installation

Import the class, and @use the entry point in your global styles. Nothing warns you when the @use is missing.

import { Component } from '@angular/core';
import { WrTransfer } from 'ngwr/transfer';

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

Basic usage

[items] is the full set and [(value)] the values on the right; ticked rows move when you press an arrow.

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

Value: [ "read" ]

Search and titles

searchable adds a filter to each list; sourceTitle and targetTitle name them.

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

In a form

[formField] or any Angular form binds the values on the right.

<!-- Signal Forms -->
<wr-transfer [items]="permissions" [formField]="form.granted" />

<!-- Reactive forms -->
<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
readonlyRefuse changes to the value while both panes stay focusable and readable. Bound automatically from the field's readonly state when used with [formField]. The move buttons go inert and the row checkboxes go read-only; SEARCH keeps working, because filtering a pane changes what is shown and not what is chosen. No aria-readonly on the host: role group does not support the state, so each row's checkbox mirrors its own instead.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
selectAllLabelAccessible name of each pane's select-all checkbox, composed with the pane heading. Falls back to transfer.selectAll.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

CSS variables

Set these on the element itself, with a rule more specific than its Declared on selector. In a global stylesheet, put a class of yours on an ancestor it really has: <body> for an overlay panel, which renders outside your markup. In a component stylesheet the selector alone works, but only for an element in that component's own template. A value on a wrapper or :root is shadowed, because ngwr/transfer declares each default on its own element.

VariableDefaultDeclared on
--wr-transfer-actions-gapvar(--wr-space-sm).wr-transfer__actions
--wr-transfer-count-font-sizevar(--wr-text-xs).wr-transfer__count
--wr-transfer-empty-font-sizevar(--wr-text-sm).wr-transfer__empty
--wr-transfer-empty-padding-xvar(--wr-space-sm).wr-transfer__empty
--wr-transfer-empty-padding-yvar(--wr-space-lg).wr-transfer__empty
--wr-transfer-font-familyvar(--wr-font-family-base).wr-transfer
--wr-transfer-gapvar(--wr-space-md).wr-transfer
--wr-transfer-head-gapvar(--wr-space-sm).wr-transfer__head
--wr-transfer-head-padding-xvar(--wr-space-md).wr-transfer__head
--wr-transfer-head-padding-yvar(--wr-space-sm).wr-transfer__head
--wr-transfer-item-padding-xvar(--wr-space-sm).wr-transfer__item
--wr-transfer-item-padding-yvar(--wr-space-xs).wr-transfer__item
--wr-transfer-item-radiusvar(--wr-border-radius-sm).wr-transfer__item
--wr-transfer-list-paddingvar(--wr-space-xs).wr-transfer__list
--wr-transfer-pane-height15rem.wr-transfer
--wr-transfer-pane-radiusvar(--wr-border-radius-base).wr-transfer__pane
--wr-transfer-pane-width14rem.wr-transfer
--wr-transfer-search-padding-xvar(--wr-space-md).wr-transfer__search
--wr-transfer-search-padding-yvar(--wr-space-sm).wr-transfer__search
--wr-transfer-title-font-sizevar(--wr-text-sm).wr-transfer__title
--wr-transfer-title-font-weightvar(--wr-font-weight-medium).wr-transfer__title

Dependencies

See also