createSelection
A composable for managing the selection of items in a collection with automatic indexing and lifecycle management.
Usage
createSelection extends createModel with selection-specific concepts: mandatory enforcement, multiple selection mode, auto-enrollment, and ticket self-methods (select(), unselect(), toggle()). It is reactive and provides helper properties for working with selected IDs, values, and items.
import { createSelection } from '@vuetify/v0'
const selection = createSelection()
selection.register({ id: 'apple', value: 'Apple' })
selection.register({ id: 'banana', value: 'Banana' })
selection.select('apple')
selection.select('banana')
console.log(selection.selectedIds) // Set(2) { 'apple', 'banana' }
console.log(selection.selectedValues.value) // Set(2) { 'Apple', 'Banana' }
console.log(selection.has('apple')) // trueContext / DI
Use createSelectionContext to share a selection instance across a component tree:
import { createSelectionContext } from '@vuetify/v0'
export const [useTabs, provideTabs, tabs] =
createSelectionContext({ namespace: 'my:tabs', multiple: false })
// In parent component
provideTabs()
// In child component
const selection = useTabs()
selection.select('tab-1')Architecture
createSelection extends createModel with auto-enrollment and ticket self-methods:
Options
| Option | Type | Default | Notes |
|---|---|---|---|
mandatory | MaybeRefOrGetter<boolean> | false | Prevent deselecting the last selected item |
multiple | MaybeRefOrGetter<boolean> | false | Allow multiple IDs to be selected simultaneously |
enroll | MaybeRefOrGetter<boolean> | false | Auto-select tickets on registration (note: createModel defaults to true) |
Reactivity
Selection state is always reactive. Collection methods follow the base createRegistry pattern.
| Property/Method | Reactive | Notes |
|---|---|---|
selectedIds | shallowReactive(Set) — always reactive | |
selectedItems | Computed from selectedIds | |
selectedValues | Computed from selectedItems | |
ticket isSelected | Computed from selectedIds | |
apply(values, options?) | — | Sync selection from external values — resolves values to IDs via browse(), then adds/removes to match |
Reactive options The mandatory, multiple, and enroll options all accept MaybeRefOrGetter<boolean>. Pass a getter to drive selection behavior from a prop or computed:
const props = defineProps<{ multiple?: boolean }>()
const selection = createSelection({ multiple: () => props.multiple ?? false })Selection vs Collection Most UI patterns only need selection reactivity (which is always on). You rarely need the collection itself to be reactive.
Examples
Bookmark Manager
Multi-component bookmark manager using provide/inject. The provider creates and shares the selection context; consumers read and toggle selections independently.
| File | Role |
|---|---|
bookmark-manager.vue | Entry point composing provider and consumers |
context.ts | Creates and types the bookmark selection context |
BookmarkProvider.vue | Provides the selection context and renders item list |
BookmarkConsumer.vue | Consumes context to display and toggle selections |
File Picker
Multi-selectable file list with disabled states, demonstrating mandatory, select(), unselect(), and the isSelected ticket property.
Selected: nothing
Functions
createSelection
(_options?: SelectionOptions) => RCreates a new selection instance for managing multiple selected items. Extends `createModel` with multi-select, mandatory enforcement, auto-enrollment, and ticket self-methods. Supports disabled items, mandatory selection enforcement, and auto-enrollment.
createSelectionContext
(_options?: SelectionContextOptions) => ContextTrinity<R>Creates a new selection context.
Options
disabled
MaybeRefOrGetter<boolean> | undefinedDisabled state for the entire model instance
Default: false
multiple
MaybeRefOrGetter<boolean> | undefinedAllow multiple tickets to be selected simultaneously
Default: false
mandatory
MaybeRefOrGetter<boolean | "force"> | undefinedControls mandatory selection behavior: - `false` (default): No mandatory selection enforcement - `true`: Prevents deselecting the last selected item - `'force'`: Automatically selects the first non-disabled item on registration
Properties
selectedValues
ComputedRef<Set<E["value"] extends Ref<infer U, infer U> ? U : E["value"]>>Computed Set of selected ticket values
Methods
move
(id: ID, toIndex: number) => E | undefinedSeek for a ticket based on direction and optional predicate
seek
(direction?: "first" | "last", from?: number, predicate?: (ticket) => boolean) => E | undefinedon
<K extends Extensible<RegistryEventName>>(event: K, cb: EventHandler<E, K>) => voidListen for registry events
off
<K extends Extensible<RegistryEventName>>(event: K, cb: EventHandler<E, K>) => voidStop listening for registry events
emit
<K extends Extensible<RegistryEventName>>(event: K, data: EventPayload<E, K>) => voidEmit an event with data
batch
<R>(fn: () => R) => RExecute operations in a batch, deferring cache invalidation and event emission until complete
Benchmarks
Every operation is profiled across multiple dataset sizes to measure real-world throughput. Each benchmark is assigned a performance tier—good, fast, blazing, or slow—and groups are scored by averaging their individual results so you can spot bottlenecks at a glance. This transparency helps you make informed decisions about which patterns scale for your use case. Learn more in the benchmarks guide.