Skip to main content
Dual Listbox with searchable panes, shared checkmarks and transfer controls ← Back to Table of Contents

Summary

Multi-select with “Available” and “Selected” panes. Supports real-time search, drag-and-drop reordering, double-click transfer, and virtual scrolling for high-performance handling of thousands of options.

Basic usage

Standard role selection

Locked options

Lock keys against transfer in the interface. Locked items already in Selected can still be reordered.
Interaction locks are not authorization rules. When a particular key must remain present or must never be granted, enforce that requirement with server-side rules and your application policy.

Custom labels and height


State & validation

Stored value

The field stores an array of keys from the options() list. The order of keys matches the order in the “Selected” pane. reorderable() controls whether users can change that order.
Use a JSON column and an Eloquent array cast for this attribute. The field validates and dehydrates form state; your Filament resource or application saves it to the model.

Validation Rules

The server rejects non-list values, nested or boolean keys, duplicates, unknown option keys and count violations. Integer keys are stored as strings. Empty selections are valid unless required(), minItems() or exactItems() says otherwise. Call the form’s validated getState() before persisting; do not save raw client properties. Apply record, tenant and permission policies in the application. You can enforce minimum or maximum selection counts:

Advanced Features

Virtual Scrolling

When the number of options exceeds 100, the component automatically enables virtual scrolling. Only the visible rows and a small buffer are rendered. Search still operates on the complete supplied option list. Adjust the threshold with virtualThreshold(100). Virtualization limits DOM work; it does not paginate options or remove the initial data payload. The supported option limit is 50,000.

Search behavior

Both panes search labels and descriptions locally. Matching ignores case and combining accents: sao matches São. Queries are limited to 256 characters. Counts show the number of matches in each pane; searching does not remove stored selections. Mark all and bulk-add actions operate on the current filtered Available list.

Double-click Transfer

Users can double-click an unlocked item to move it to the other pane, subject to the maximum selection count. This can be disabled via moveOnDoubleClick(false).

Reorder selected items

Drag items in the Selected pane to change order, including locked (disabledOptions) rows. Those rows cannot be moved to Available. Arrow buttons remain as an accessible fallback. Disable both with reorderable(false). On stacked (narrow) layouts, transfer arrows point up and down.

Multi-select on touch

Tap options to mark several without modifiers. On desktop, click the checkmark to toggle individual marks, use Cmd/Ctrl + click for additive selection, or Shift + click for a range. On phones and tablets, scroll the list normally. Hold one item still for a moment to pick it up — a stacked preview follows that thumb, with a count badge when more than one item is held. Tap more items with another finger to add them to the stack. After you drop the group, the highlight is cleared. Drop on the Selected list to insert before or after a row (upper vs lower half), or on Available to remove items from Selected. Transfer buttons still move the whole selection. On desktop, hold Cmd/Ctrl (or Shift for a range) and use drag-and-drop in the Selected pane.

Keyboard and RTL

Set dir="rtl" on the surrounding form or container. Pane layout, action direction and logical spacing follow that direction. Narrow containers stack the panes and rotate transfer arrows vertically. Long labels and descriptions are truncated in fixed-height rows; the full text remains in the row’s title.

Rich options

Custom Icons

Transfer, reorder and search icons can be customized to match your UI. Pane heading icons, the lock indicator and the shared Checklist checkmark are fixed.

Configuration API

Configuration methods below accept a Closure. icons() evaluates its map when called; use the individual icon setters for icons that must be evaluated with the field context.

Option format and localization

Option keys must be strings or integers with valid UTF-8 text, at most 512 bytes and without control characters. Labels accept up to 4,096 bytes and descriptions up to 8,192 bytes of UTF-8 text. A rich option may contain label, description and the boolean disabled flag; omitting label uses its key. Supply plain text, not HTML. availableLabel() and selectedLabel() customize pane headings. Search placeholders, empty states, action labels and keyboard hints use the package translations. Override keys in your application’s lang/vendor/filament-flex-fields/en/default.php (change en for another locale):

Real-world examples

User Permissions Management

Use your application’s Permission model. Convert the query result to an array; options() does not accept a Collection.

Exactly three choices

Minimal and read-only interfaces

A read-only field keeps its value available for normal form submission. A disabled field follows Filament’s dehydration policy and is excluded by default unless explicitly configured otherwise. Both prevent interaction.

Sizes and variants

The bordered variant name is retained for compatibility; its current workspace and option cards do not add outlines. The three variants change the workspace surface. Search follows the shared Flex Text Input presentation independently. When options() depends on another field, its closure is reevaluated on the server. Reset or replace the selected value when the permitted options change; outdated keys fail validation rather than being silently accepted.

Playground

/admin/flex-fields/dual-listbox when the panel uses the /admin prefix. The playground includes descriptions, interaction locks, three sizes, visual variants, read-only and disabled fields, selection limits and a 1,000-option virtual list. See Installation for setup.

Appearance and icon configuration

The workspace has a 24 px outer radius. Its inner panels derive their radius from that value minus the 8 px workspace inset (16 px), so nested corners remain aligned. Scroll edges use fixed gradients that fade in and out; reaching the start or end removes the corresponding fade. Search reuses Flex Text Input’s shell and control with its shadow-free primary variant and whole-control focus outline. Option cards remain visible before hover. Checkmarks share the same shape and animation as Flex Checklist. Both controls use Hugeicons by default and respect reduced-motion preferences. icons() accepts these keys: search, move_all_right, move_right, swap, move_left, move_all_left, move_up, move_down. Individual setters are searchIcon(), moveAllRightIcon(), moveRightIcon(), swapIcon(), moveLeftIcon(), moveAllLeftIcon(), moveUpIcon() and moveDownIcon(); each accepts a registered icon name, enum, HTML icon or closure. listHeight() accepts a positive simple length in px, rem, em, vh or dvh. Count settings accept 0–50,000 or null; the minimum cannot exceed the maximum. rounding() configures the shared rounding token, including search controls; it does not change the workspace’s outer 24 px radius.

CSS classes (reference)

Last modified on October 16, 2026