Skip to main content
Vuetify0 is now a release candidate!
Vuetify0 Logo
Theme
Mode
Palettes
Accessibility
Vuetify One
Sign in to Vuetify One

Access premium tools across the Vuetify ecosystem — Bin, Play, Studio, and more.

Not a subscriber? See what's included

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.

ts
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')) // true

Context / DI

Use createSelectionContext to share a selection instance across a component tree:

ts
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:

Selection Hierarchy

Use controls to zoom and pan. Click outside or press Escape to close.

Selection Hierarchy

Options

OptionTypeDefaultNotes
mandatoryMaybeRefOrGetter<boolean>falsePrevent deselecting the last selected item
multipleMaybeRefOrGetter<boolean>falseAllow multiple IDs to be selected simultaneously
enrollMaybeRefOrGetter<boolean>falseAuto-select tickets on registration[1]

Reactivity

Selection state is always reactive. Collection methods follow the base createRegistry pattern.

Property/MethodReactiveNotes
selectedIdsshallowReactive(Set) — always reactive
selectedItemsComputed from selectedIds
selectedValuesComputed from selectedItems
ticket isSelectedComputed from selectedIds
apply(values, options?)Sync selection from external values — resolves values to IDs via browse(), then adds/removes to match
Tip

Reactive options The mandatory, multiple, and enroll options all accept MaybeRefOrGetter<boolean>. Pass a getter to drive selection behavior from a prop or computed:

ts
const props = defineProps<{ multiple?: boolean }>()
const selection = createSelection({ multiple: () => props.multiple ?? false })
Tip

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

A full bookmark manager spread across three components, demonstrating createSelection paired with createContext to share selection state via provide/inject without prop-drilling.

context.ts defines the BookmarkContext interface — which extends SelectionContext and adds pinnedIds, stats, and pin/unpin helpers — then exports the createContext tuple [useBookmarks, provideBookmarks]. BookmarkProvider.vue calls createBookmarks() (which calls createSelection({ multiple: true, events: true })), seeds seven items including one disabled entry, builds the extended context object, and calls provideBookmarks() to make it available to all descendants. It is a renderless wrapper: its template is just <slot />. BookmarkConsumer.vue injects the context with useBookmarks() and uses useProxyRegistry to iterate tickets reactively — it never holds a reference to the selection instance directly.

The consumer exposes tag-based filtering via a local filter ref and derived filtered computed, select-all and clear-all bulk actions, an add-bookmark form, a pin/unpin button per row, and a live stats bar. All selection mutations go through bookmarks.toggle(), bookmarks.select(), and bookmarks.unselect() — the same API whether you’re in the consumer or anywhere else in the tree.

This pattern is the right shape when a selection instance needs to be created in one component but read or mutated in unrelated components below it. Compare to the Playlist Builder below for the no-DI alternative — the same selection API driven from a plain composable, with no provide/inject.

FileRole
bookmark-manager.vueEntry point composing provider and consumers
context.tsCreates and types the bookmark selection context
BookmarkProvider.vueProvides the selection context and renders item list
BookmarkConsumer.vueConsumes context to display and toggle selections
7 bookmarks0 selected1 pinned
Vue.js
|
Vue.jshttps://vuejs.org
framework
Vitehttps://vite.dev
tooling
Piniahttps://pinia.vuejs.org
framework
Vitesthttps://vitest.dev
tooling
MDN Web Docshttps://developer.mozilla.org
reference
Can I Usehttps://caniuse.com
reference
Legacy API (deprecated)https://example.com
reference

Playlist Builder

A multi-select track list with a select-all lever and a bulk “add to queue” action, built on createSelection directly — no createContext, no provide/inject. State lives in a plain composable and is passed down as a single prop, the simplest way to share a selection instance between two components.

useTracklist.ts calls createSelection({ multiple: true }) once and onboard()s seven tracks in a single pass, mapping each track’s unavailable flag onto the ticket’s disabled input so the inert row can never be selected. It exposes the returned tickets array plus a few derived signals: count (a toRef over selectedIds.size), allSelected (a toRef that folds every selectable ticket’s isSelected), and the bulk operations toggleAll, enqueue, and clearQueue. enqueue() reads selection.selectedValues.value — the reactive Set of selected track objects — then calls selection.reset() to clear the selection in one shot.

TrackList.vue is purely presentational: it receives the composable’s return value as a tracklist prop and renders the toolbar and rows, reading ticket.isSelected.value, calling ticket.toggle() per row, and driving the header checkbox from allSelected / toggleAll. Reach for this shape when selection state needs to live above the markup but a full context provider would be overkill; when the instance must be reachable from unrelated parts of the tree instead, see the Bookmark Manager above for the provide/inject split. Related: createSingle for single-select and createGroup for tri-state select-all.

FileRole
useTracklist.tsOwns the track data, selection instance, derived signals, and bulk actions
TrackList.vuePresentational list and toolbar driven by the composable’s return value
track-list.vueEntry point wiring the composable to the list and rendering the queue summary

Select tracks and add them to the queue.

FAQ

Discord
Need help? Join our community for support and discussions ↗

API Reference

The following API details are for the createSelection composable.

  1. createModel flips this default to true since two-way-bound items are typically expected to start enrolled. ↩︎

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.

View benchmark source↗

Was this page helpful?

Ctrl+/